I have simple example of my problem. There ara two students and three subjects. At the beginning student1 has all subjects, student2 has no subjects. Relation is one student and many subjects.
I'm trying to swap subject1 from student1 to student2 with jpa hibernate. After transaction commit change appears in database: foreign key student_id of subject table is changed, but in java student1 object is still have subject1 even if I load student1 from database.
@Entity
@Table(name = "STUDENTS")
public class Students {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ST_ID")
private int id;
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
List<Subject> subjects = new ArrayList<>();
//getters and setters....
}
@Entity
@Table(name = "SUBJECT")
public class Subject {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "SB_ID")
private int id;
@Column(name = "MARK")
private int mark;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ST_ID")
private Students student;
//getters and setter....
}
Main code:
public static void main(String[] args) throws Exception {
EntityManager em = Persistence.createEntityManagerFactory("Test").createEntityManager();
// em.getTransaction().begin(); //does not work
Students student1 = getStudentById(1, em); //load student1 from database by id
Students student2 = getStudentById(2, em); //load student2 from database by id
Subject subject1 = getSubjectById(1, em); //load subject1 from database by id
Subject subject2 = getSubjectById(2, em); //load subject2 from database by id
Subject subject3 = getSubjectById(3, em); //load subject3 from database by id
System.out.println("student1 subjects");
for(Subject sb : student1.getSubjects()){
System.out.println(sb.getId()); //prints subjects: 1,2,3
}
System.out.println("\nstudent2 subjects");
for(Subject sb : student2.getSubjects()){
System.out.println(sb.getId()); //prints no subjects
}
//swap subject1 between student1 and student2
subject1.setStudent(student2);
student2.getSubjects().add(subject1);
//save changes
em.getTransaction().begin();
em.persist(student2);
em.persist(student1);
em.persist(subject2);
em.persist(subject1);
//em.merge does't work
//em.flush(); //doesn't work
em.getTransaction().commit();
student1 = getStudentById(1, em); //load student1 from database by id
System.out.println("\nstudent1 subjects");
for(Subject sb : student1.getSubjects()){
System.out.println(sb.getId()); //and still student1 has subject1
}
student2 = getStudentById(2, em); //load student2 from databse by id
System.out.println("\nstudent2 subjects");
for(Subject sb : student2.getSubjects()){
System.out.println(sb.getId()); //now student2 also has subject1
}
}
public static Students getStudentById(int id, EntityManager em){
Query query = em.createQuery("from entity.Students where ST_ID="+id);
return (Students)query.getSingleResult();
}
public static Subject getSubjectById(int id, EntityManager em){
Query query = em.createQuery("from entity.Subject where SB_ID="+id);
return (Subject) query.getSingleResult();
}
After commit subject table looks like this. It shows that subject with id 1 now has student with id 2.
Entity object student1 is only updated if I make em.refresh after commit, but I don't understand why I need to use refresh if I load student1 from database? And also I'm not sure, is refresh entity is good practice?