How to force a zero to one relationship? - java

My requirement is to have a list of classes and students of each class. Each students must be in zero or at most one class. My code is as following, but in database, each student can be in many classes. How to keep each student in zero to one and only one class?
Student item table is as following
StudentItem
id student_id code
1 1 233
2 5 453
3 1 567
4 6 565
Entities
#Entity
public class MyClass{
#Id
#GeneratedValue
private long id;
#OneToMany( cascade = CascadeType.ALL)
#LazyCollection(LazyCollectionOption.FALSE)
private List<StudentItem> students;
private String season;
...
}
#Entity
public class StudentItem{
#Id
#GeneratedValue
private long id;
#OneToOne
private Student student;
private String code;
...
}
#Entity
public class Student{
#Id
#GeneratedValue
private long id;
private String fname;
private String lname;
....
}

It seems to me that it's a many-to-one relationship between MyClass and StudentItem, with MyClass owning the relationship between them. Further, it may be simpler and more straightforward to use a join table between these two entities; this way, you don't run the risk of creating more than one MyClass entry in your database.
Think of it like this: what is the actual effective relationship between a class and a student? From your description, one class may hold many students, but any given student may only be in one class.
Here's a rough-hand example from memory on how to create it. I'll assume that there is a joining table between StudentItem and MyClass called classroom_students, with columns student_item_id and class_id.
#Entity
public class MyClass {
#Id
#GeneratedValue
private Integer id;
#OneToMany
#JoinTable(name = "classroom_students",
joinColumns = #JoinColumn(name = "student_item_id"),
inverseJoinColumns = #JoinColumn(name = "class_id"))
private List<MyClass> students;
// getters and setters for entity
}
#Entity
public class StudentItem {
#Id
#GeneratedValue
private Integer id;
#OneToOne(mappedBy = "student_id")
private Student student;
#ManyToOne(targetEntity = MyClass.class,
mappedBy = "students")
private MyClass myClass;
}

Related

Spring data JPA save and updating parent entity

I have two entities called Student and Subject. They are stored in tables in the following format
student_id
name
grade
1
John
1
subject_id
name
1
English
2
Math
subject_id
student_id
mark
1
1
75
2
1
75
**Student:**
#Table(name = "student")
#Data
public class Student {
#Id
#GeneratedValue(strategy = IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "grade")
private int grade;
//getters and setters left out for this example
}
**Subject:**
#Table(name = "subject")
#Data
public class Subject {
#Id
#GeneratedValue(strategy = IDENTITY)
private Long id;
#Column(name = "name")
private String name;
//getters and setters left out for this example
}
**StudentRepository:**
public interface StudentRepository extends JpaRepository<Student, Long> {
}
How do I make it so that everytime I add a student using a StudentController, the subjects are automatically added to the student.
Create the third entity for the third table, create the student object and the subject object . put it in the third entity object, create the third repository and save that, all three tables will be updated together. Just make sure your relationships are correctly mentioned and you are done.
Update your Student entity to encapsulate Subject.
The idea is to explicitly define relationship between Student and Subject , and further leverag Cascade to propagate changes :
#Table(name = "student")
#Data
public class Student {
#Id
#GeneratedValue(strategy = IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "grade")
private int grade;
#OneToOne(cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE}, orphanRemoval = true)
#JoinColumn(name = "SUBJECT_ID")
Subject subject;
}
Note : You need to make sure that you populate Subject when storing Student.
For more clarity , explore the examples presented here : https://vladmihalcea.com/a-beginners-guide-to-jpa-and-hibernate-cascade-types/

Hibernate #ManyToMany with extra columns

So I've been trying the solutions out there to map a ManyToMany relationship with extra columns but none of them is working for me and I don't know what am I doing wrong.
The Many to Many relationship is between Patient and Disease (a Patient can have multiple diseases and a Disease can be suffered by many Patients). The time attribute means "the type of the disease" (acute, chronic...)
My classes are:
#Entity
#Table(name="patient")
public class Patient{
#Id
#NotNull
#Column(name="nss")
private String NSS;
//Some attributes
#OneToMany(mappedBy = "patient")
private Set<PatientDisease> diseases = new HashSet<PatientDisease>();
//Empty constructor and constructor using fields omitted
//Getters and setters ommited
}
,
#Entity
#Table(name="disease")
public class Disease{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#OneToMany(mappedBy = "disease")
private Set<PatientDisease> patients = new HashSet<PatientDisease>();
//Constructors and getters and setters ommited for brevity
}
Associated class
#Entity
#Table(name = "Patient_Disease")
#IdClass(PatientDiseaseID.class)
public class PatientDisease{
#Id
#ManyToOne(fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
#JoinColumn(name = "nssPatient", referencedColumnName = "id")
private Patient patient;
#Id
#ManyToOne(fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
#JoinColumn(name = "diseaseID", referencedColumnName = "id")
private Disease disease;
#Column(name="time")
private String time;
//GETTERS AND SETTERS OMMITED FOR BREVETY. Constructor NOT Needed following the example
}
The id class:
#Embeddable
public class PatientDiseaseId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "nssPatient")
private String patient;
#Column(name = "diseaseID")
private Integer disease;
//getters and setters
//hashCode and equals
}
My main app:
...
List<Diseases> diseases = sesion.createQuery("from Disease").getResultList();
System.out.println("Diseases: ");
for(Disease d: diseases) {
System.out.println(d.getName());
for(PatientDisease pd: e.getPatientDisease()) {
System.out.println(pd.getPatient().toString());
}
}
...
When running the main App I get the exception on line 5 (2nd for loop):
Exception in thread "main" org.hibernate.PropertyAccessException: Could not set field value [1] value by reflection : [class entities.PatientDisease.diseases] setter of entities.PatientDisease.diseases
I have tried some solutions here in Stack Overflow an some others that I found on the Internet, but I can't get them to work and I don't know why
Because you are using #IdClass you don't need to annotate PatientDiseaseId with #Embedded and #Column. And you have to refer to the entities.
This is what it should look like:
public class PatientDiseaseId implements Serializable {
private static final long serialVersionUID = 1L;
private Patient patient;
private Disease disease;
//getters and setters
//hashCode and equals
}

Hibernate Spring annotation confused

I'm confused in S. H. Annotation. Here is my code
for my first class:
#Entity
#Table(name="player")
public class Player implements Serializable
{
#Id
#Column(name="id_player")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private String pseudo;
}
and my second class:
#Entity
#Table(name="team")
public class Team implements Serializable
{
#Id
#Column(name="id_team")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "player")
private Set<Player> players = new HashSet<Player>();
}
it throws the exception:
mappedBy reference an unknown target entity property:
Player.Team in Team.players
i have getters and setters in these class.
how can i make it works? Thank you!
Add this in Player Class:
#ManyToOne(fetch = FetchType.LAZY)
private Team team;
And replace in Team Class:
mappedBy = "player" ----> mappedBy = "team"

Hibernate Mapping when foreign key placed in reference class

I have two classes Student and Address.
Student{
stuid,
stuName,
}
Address{
street,
city,
stuid;//foriegn key Ref with Studnet
}
Can any one help me to map these two classes using hibernate??
You should learn what is OneToOne mapping in hibernate firstly.
Secondly if I would want to design then I would have address_id as foreign key in Student table and not student id.
//Table name will be taken as Student as you are not specifying it using #Table annotation
Student class
#Entity
public class Student{
#Id
#Column("stuid")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column("stuName")
private String name;
//setters and getters
}
Address class
#Entity
public class Address{
#Id
#Column("add_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column("street")
private String street;
#Column("city")
private String city;
#OneToOne(cascade={CascadeType.SAVE,CascadeType.MERGE})
#JoinColumn(name="stuid")
private Student student
//setters and getters
}
Suppose if a Student can have multiple Address entities then you need to have one-to-many relationship between Student and Address classes. A student should know what addresses they belong to and also as you need to save the student id in address table then the relationship becomes bi-directional.
The entities looks like this:
Student.java
#Entity
#Table(name = "student_tbl") // Optional, By default table name is student, if you want to give different name then use this line.
public class Student1 {
#Id
#GeneratedValue
private int stuid;
private String stuName;
#OneToMany(mappedBy = "student")
private List<Address> address = new ArrayList<Address>();
// Setters & Getters
}
Address.java
#Entity
#Table(name = "address_tbl")
public class Address {
#Id
#GeneratedValue
private int addressId;
private String street;
private String city;
#ManyToOne
#JoinColumn(name="stuid")
private Student1 student;
// Setters & Getters
}

Spring MVC Hibernate Many to Many Relationship get org.hibernate.exception.SQLGrammarException: Unknown column in 'on clause'

I have 3 class which is have a relation like this
#Entity
#Table(name="tbl_mhs")
public class ModelStudent {
#Id
#GeneratedValue
#Type(type="java.lang.Integer")
#Column(name="id_student")
private Integer id;
#ManyToMany(cascade = {CascadeType.ALL})
#LazyCollection(LazyCollectionOption.FALSE)
#JsonIgnore
#JoinTable(name="tbl_course_selected",
joinColumns={#JoinColumn(name="id_student")},
inverseJoinColumns={#JoinColumn(name="id_course")})
private List<ModelCourse> course;
and here the 2nd class
#Entity
#Table(name="tbl_makul")
public class ModelCourse {
#Id
#GeneratedValue
#Type(type="java.lang.Integer")
#Column(name="id_course")
private Integer id;
#ManyToMany(cascade = {CascadeType.ALL})
#LazyCollection(LazyCollectionOption.FALSE)
#JsonIgnore
#JoinTable(name="tbl_course_selectedl",
joinColumns={#JoinColumn(name="id_course")},
inverseJoinColumns={#JoinColumn(name="id_student")})
private List<ModelStudent> student;
and then the third class
#Entity
#Table(name="tbl_materi")
public class ModelBook {
#Id
#GeneratedValue
#Type(type="java.lang.Integer")
#Column(name="id_book")
private Integer id;
#ManyToOne
#JoinColumn(name="id_course")
private ModelCourse course;
What i want here is getting all of the book from course which is selected by student. So in the DAOImpl my code is like this
List<ModelBook> books = new ArrayList<ModelBook>();
Criteria criteria = getCurrentSession().createCriteria(ModelBook.class);
criteria.createAlias("course", "courseAlias");
criteria.createAlias("courseAlias.student", "studentAlias");
criteria.add(Restrictions.eq("studentAlias.id", student_id));
return criteria.list()
when I executed my application I got this exception
nested exception is org.hibernate.exception.SQLGrammarException: Unknown column 'student9_.id_student' in 'on clause'
What I'm doing wrong here?
Thank you for the answer, sorry for my bad english
Try below code for many-to-many. Also, use variable names instead of column names if you use HQL
#ManyToMany(mappedBy = "course", cascade = {CascadeType.ALL})
#LazyCollection(LazyCollectionOption.FALSE)
#JsonIgnore
private List<ModelStudent> student;

Categories