I am trying to set up a very simple database with two tables in Java and connect them using a specific connection table.
1st table Student consists of id, first_name and last_name.
2nd table Course consists of id and name.
The connection table called Enrollment should have course_id and student_id that originate from 1st and 2nd tables.
My problem is I don't know how to map the IDs when extending Spring Data JPA's AbstractPersistable, which has an auto-increment primary key field in it.
My code:
Student:
// Package
// Imports
#Entity
#Data #NoArgsConstructor #AllArgsConstructor
public class Student extends AbstractPersistable<Long> {
private String first_name;
private String last_name;
}
Course:
// Package
// Imports
#Entity
#Data #NoArgsConstructor #AllArgsConstructor
public class Course extends AbstractPersistable<Long> {
private String name;
}
I have tried different usages of #ManyToMany annotation but since the primary key ID is handled by AbstractPersistable, I have failed to map the 'invisible' IDs for the connection table.
I also know that the connection table and its columns can be named with #Column, #JoinColumn and #JoinTable. I haven't gotten that far yet.
Hi i would try something like this ...
#Entity
#Data #NoArgsConstructor #AllArgsConstructor
public class Student extends AbstractPersistable<Long> {
private String first_name;
private String last_name;
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(name = "enrollment",
joinColumns = #JoinColumn(name = "student_id"),
inverseJoinColumns = #JoinColumn(name = "course_id")
)
private List<Course> courses;
}
#Entity
#Data #NoArgsConstructor #AllArgsConstructor
public class Course extends AbstractPersistable<Long> {
private String name;
#ManyToMany(mappedBy = "courses")
private List<Student> students;
}
Related
I'm currently working on developing a recipe application and I'm having trouble with DB table generation.
Here are the Entity files I'm using:
// Recipe.java
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "recipes")
public class Recipe {
#Id
#GeneratedValue
private int id;
private String name;
private String description;
private String instruction;
#ManyToOne
private User user;
#OneToMany(cascade=CascadeType.ALL)
private List<RecipeIngredient> ingredients = new ArrayList<>();
}
// Ingredient.java
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "ingredients")
public class Ingredient {
#Id
#GeneratedValue
private int id;
private String name;
}
// RecipeIngredient.java
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
public class RecipeIngredient {
#Id
#GeneratedValue
private int id;
#ManyToOne
private Ingredient ingredient;
private String amount;
}
Spring Boot Automatically creates tables for me but I just wanna have one table for RecipeIngredient, but it creates two tables for them.
It works perfectly fine but the thing I want is just how to make these two tables into one or make spring boot not generate one of them.
If you want recipe_ingedients table only delete recipeIngredient Entity Class and if you want to keep recipe_ingredient table remove this:
#OneToMany(cascade=CascadeType.ALL)
private List<RecipeIngredient> ingredients = new ArrayList<>();
Hello I am new to JPA Spring boot and right now I am trying to make a connection between two tables into a third one. So I have a Doctor and Patient table with it's properties, where one Doctor can examine every patient and a patient can visit every doctor.But in one examination there can be no more than one patient and one doctor. For the doctors I want to keep the information of which patients they have examined, respectively for the patients, which doctors they were examined from. I would like to create a middle table called DoctorVisit where I have the id of the doctor who did the examination and the id of the patient with some more properties like date,medicines and etc. When I try to do this I am getting an error - "mappedBy reference an unknown target entity property: /.../Patient.examinedByDoctors". If I remove the #OneToMany connection in Patient the code compiles. I would be really happy if someone can explain me where is the mistake. Thank you in advance
BaseEntity class:
#Getter
#Setter
#NoArgsConstructor
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private long id;
}
Doctor class:
#Getter
#Setter
#NoArgsConstructor
#Entity
#Table(name="doctor")
public class Doctor extends BaseEntity{
private String name;
#ManyToMany(mappedBy ="doctors")
private Set<Specialty> specialties;
#OneToMany(mappedBy ="doctor")
private Set<Patient> GpOfPatients;
#OneToMany(mappedBy = "doctor")
private List<Patient> examinedPatients;
}
Patient class:
#Getter
#Setter
#NoArgsConstructor
#Entity
#Table(name="patient")
public class Patient extends BaseEntity{
private String name;
private String EGN;
private boolean insurancesPaidInLastSixMonths;
#ManyToOne
#JoinColumn(name="gp_id")
private Doctor doctor;
#OneToMany(mappedBy = "patient")
private List<Doctor> examinedByDoctors;
}
Specialty class:
#Getter
#Setter
#NoArgsConstructor
#Entity
#Table(name="specialty")
public class Specialty extends BaseEntity{
private String specialtyName;
#ManyToMany
#JoinTable(name="doctors_specialties",joinColumns = #JoinColumn(name="specialty_id"),
inverseJoinColumns = #JoinColumn(name="doctor_id"))
private Set<Doctor> doctors;
}
DoctorVisit class:
#Getter
#Setter
#NoArgsConstructor
#Entity
#Table(name="doctorvisit")
public class DoctorVisit extends BaseEntity {
#ManyToOne
#JoinColumn(name = "patient_id")
private Patient patient;
#ManyToOne
#JoinColumn(name="doctor_id")
private Doctor doctor;
private Date date;
private String diagonosis;
#ManyToMany(mappedBy = "prescribedToPatients")
private Set<Medicine> medicines;
private int patientChart;
}
Medicine class:
#Getter
#Setter
#Entity
#Table(name = "medicine")
public class Medicine extends BaseEntity{
private String name;
private String manufacturer;
#ManyToMany
#JoinTable(name="prescribedMedicines_to_patients",joinColumns = #JoinColumn(name="medicine_id"),
inverseJoinColumns = #JoinColumn(name="patient_id"))
private List<Patient> prescribedToPatients;
}
You get this error because the Doctor class does not have a patient field. However adding a Patient won't fit your use case, because a Doctor can have multiple Patients not just one. So you have to create a ManyToMany association between Patient and Doctor or use only the DoctorVisit to connect the two entities. I would apply the second option and use special queries to get who visited who with the DISTINCT keyword for example.
I'm using a JPARepository called PublicationRepository and want to find all Publications from a certain Person. This Classes are connected over the Class Author.
Person Class:
#Entity
public class Person {
#Id
private String email;
private String telefon;
private String password;
#OneToMany(mappedBy = "person")
Set<Author> Author;
}
Author Class:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Author {
#Id
private int id;
#ManyToOne
#JoinColumn(name="Person_ID")
Person person;
#ManyToOne
#JoinColumn(name="Publication_ID")
Publication publication;
private String Date;
private String Writerstatus;
}
Publication Class
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Data
public class Publication {
#Id
private int id;
private String publicationname;
#OneToMany(mappedBy = "publication")
Set<Author> author;
}
And the PublicationRepository
public interface ProjektRepository extends JpaRepository<Projekt,Integer> {
}
public interface PublicationRepository extends JpaRepository<Publication,Integer> {
#Query(value = "SELECT pub.* FROM author as auth INNER JOIN publications as pub ON auth.publication_id = pub.id WHERE auth.person_id = ?1", native = true)
List<Publication> findAllPublicationsOfThisPerson(int personId);
}
Try this.
I would also recommend to annotate the entities with their table names:
#Table(name = "publication")
You use a manually build table for a Many-to-Many relationship Author
You could also delegate that to Spring Data Jpa by using #ManyToMany Annotation.
A good tutorial:
https://attacomsian.com/blog/spring-data-jpa-many-to-many-mapping
This is STUDENTS ENTITY
#Entity
#Table(name = "STUDENTS")
public class Student extends BaseEntity {
#Column(name = "student_index")
public String index;
public String firstName;
public String lastName;
#ManyToMany
public List<Course> courses;
}
This is COURSES ENTITY
#Entity
#Table(name = "COURSES")
public class Course extends BaseEntity {
public String name;
#ManyToMany
public List<Student> students;
}
Which tables will be generated in DataBase?
There must be tables
STUDENTS, COURSES, STUDENTS_COURSES, COURSES_STUDENTS
The #ManyToMany will be confused and will create two tables STUDENTS_COURSES, COURSES_STUDENTS
To avoid such situation need to provide option mappedBy
ie.
#ManyToMany(mappedBy = "STUDENTS")
it will create only one table STUDENTS_COURSES
I have 3 Entities:
#Data
#AllArgsConstructor
#Entity
#Table(name = "beneficiary")
#Inheritance
#DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "type")
public abstract class Beneficiary {
public Beneficiary() {}
#Id private String id;
private String description;
}
#Data
#Entity
#DiscriminatorValue("company")
#EqualsAndHashCode(callSuper = true)
public class BeneficiaryCompany extends Beneficiary {
public BeneficiaryCompany() {
super();
}
public BeneficiaryCompany(String id, String description) {
super(id, description);
}
}
#Data
#Entity
#DiscriminatorValue("person")
#EqualsAndHashCode(callSuper = true)
public class BeneficiaryPerson extends Beneficiary {
public BeneficiaryPerson() {}
public BeneficiaryPerson(String id, String description) {
super(id, description);
}
}
An in the other class I want to have 2 separate collections:
#Data
#AllArgsConstructor
#Entity
#Table(name = "transaction")
public class Transaction {
public Transaction() {}
#Id private String id;
private String description;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = BeneficiaryCompany.class)
#JoinColumn(name = "transaction_id", nullable = false)
private Set<BeneficiaryCompany> beneficiaryCompanies;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true,targetEntity = BeneficiaryPerson.class)
#JoinColumn(name = "transaction_id", nullable = false)
private Set<BeneficiaryPerson> beneficiaryPeople;
}
The problem is that every Beneficiary was fetched into beneficiaryCompanies, and beneficiaryPeople in the debugger tells me that:
Unable to evaluate the expression Method threw
'org.hibernate.WrongClassException' exception.
The database records looks fine (DiscriminatorColumn was created). What could be the problem? Why beneficiaryCompanies contains BeneficiaryPerson objects?
#EDIT:
To fetch the records I am using SpringData JPA repositories.
Use #MappedSuperclass on your base class Beneficiary
Alexandar Petrov is absolutely correct. You have to remove #Entity because superclass is not an entity. When dealing with inheritance extending a class, you can use #MappedSuperclass annotation on the base class, in your case, it is Beneficiary.
Edit:
This is a very good article you can refer to.