Java – JPA, many to many relationship, delete all previous relationships and enter new relationships
Here, I am trying the many to many relationship in JPA. I have created tables "tblcourse" and "tblstudent". Students can register for many courses,
create table tblcourse( id integer primary key,name varchar(100),duration integer ); create table tblcourseStudent( studentid integer references tblstudent(studentId),courseId integer references tblcourse(id),constraint pk_composit_cs primary key(studentid,courseId) ) Create table tblStudent( studentId integer primary key,…….. …. );
The JPA representation of the above relationship is as follows. This is studententity Java code,
@Entity @Table(name="TBLSTUDENT") public class StudentEntity implements Serializable{ private static final long serialVersionUID = 100034222342L; @Id @Column(name="STUDENTID") private Integer studentId; @Column(name="STUDENTNAME") private String studentName; @Column(name="CONTACTNO") private String contactNumber; @Embedded private StudentAddress address; @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="DEPTID") private DeptEntity deptEntity; @ManyToMany(fetch=FetchType.LAZY) @JoinTable(name="tblcourseStudent",joinColumns=@JoinColumn(name="studentid"),inverseJoinColumns=@JoinColumn(name="courseId")) private List<CourseEntity> courseList; .... ..... ..... }
This is courseentity Java code,
@Entity @Table(name="TBLCOURSE") public class CourseEntity implements Serializable{ public CourseEntity(){ } public CourseEntity(Integer courseId,String courseName,Integer courseDuration){ this.courseId = courseId; this.courseName = courseName; this.courseDuration = courseDuration; } /** * */ private static final long serialVersionUID = -2192479237310864341L; @Id @Column(name="ID") private Integer courseId; @Column(name="NAME") private String courseName; @Column(name="DURATION") private Integer courseDuration; @ManyToMany(fetch=FetchType.LAZY) @JoinTable(name="tblcourseStudent",joinColumns=@JoinColumn(name="courseId"),inverseJoinColumns=@JoinColumn(name="studentid")) private List<StudentEntity> studentList; ......... }
Now, when I try to pass studententity When Java is inserted into the course, the SQL query triggered at the back end is
delete from tblcourseStudent where studentid=? insert into tblcourseStudent (studentid,courseId) values (?,?) insert into tblcourseStudent (studentid,?)
And when I try to pass courseentity When Java is inserted into a student, the SQL query triggered is as follows,
delete from tblcourseStudent where courseId=? insert into tblcourseStudent (courseId,studentid) values (?,?)
In both cases, the record is deleted and a new mapping is inserted Therefore, if I insert a course for a student, I will first delete all previous courses for the student from the third table and enter a new course,
So my question is, if I don't want to delete the old course and add a new course for students, how can I do it, that is, I want to keep the old relationship,
Weather, I have to achieve this goal programmatically, or I change the comment and wait for a reply
When we map a student to multiple courses, we call studentservicebean Code written in Java and the "mapstudenttocourses" method
@Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class StudentServiceBean implements StudentService{ @PersistenceContext(unitName="forPractise") private EntityManager entityMgr; @Resource private SessionContext sessionContext; @EJB private DeptService deptService; .......... ...... ... @Override @TransactionAttribute(TransactionAttributeType.required) public void mapStudentToCourses(Integer studentId,String courseIdList) throws Exception{ List<CourseEntity> courseList = null; StudentEntity studentEntity = null; TypedQuery<CourseEntity> courseQuery = null; String query = "select c from CourseEntity c where c.courseId in ("+courseIdList+")"; try{ courseQuery = entityMgr.createQuery(query,CourseEntity.class); courseList = courseQuery.getResultList(); studentEntity = entityMgr.find(StudentEntity.class,studentId); studentEntity.setCourseList(courseList); entityMgr.merge(studentEntity); }catch(Exception e){ sessionContext.setRollbackOnly(); throw e; } }
This is to map a course to multiple students and their courseservicebean Java code
@Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class CourseServiceBean implements CourseService{ @PersistenceContext(name="forPractise") private EntityManager em; @Resource private SessionContext sessionCtx; private Map<Integer,String> durationCode = null; @EJB private StudentService studentService; ........ ...... ... @Override @TransactionAttribute(TransactionAttributeType.required) public void mapCourseToStudents(Integer courseId,String studentIdList) throws Exception{ List<StudentEntity> studentEntityList = null; TypedQuery<StudentEntity> studentQuery = null; String query = "select s from StudentEntity s where s.studentId IN ("+studentIdList+")"; CourseEntity courseEntity = null; try{ studentQuery = em.createQuery(query,StudentEntity.class); studentEntityList = studentQuery.getResultList(); courseEntity = em.find(CourseEntity.class,courseId); courseEntity.setStudentList(studentEntityList); em.merge(courseEntity); }catch(Exception e){ sessionCtx.setRollbackOnly(); throw e; } } }
This is my persistence XML file,
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="forPractise" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>jdbc/app</jta-data-source> <class>com.entity.StudentEntity</class> <class>com.entity.DeptEntity</class> <class>com.entity.CourseEntity</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence>
Waiting for reply
Solution
I may be wrong, but I think this is normal. When you insert, hibernate deletes all records in the associated table for the first time
This is why: when using x-to-many associations (basically associations mapped through the collection), hibernate's persistence context will perform dirty checks based on the identifier of the collection
We get the mapcoursetostudents() method from the courseservicebean class:
... studentQuery = em.createQuery(query,StudentEntity.class); studentEntityList = studentQuery.getResultList(); courseEntity = em.find(CourseEntity.class,courseId); courseEntity.setStudentList(studentEntityList); // replacing the prevIoUs Collection by the one you retrieved by querying the DB !!! em.merge(courseEntity); ...
If you really want to avoid hibernate from executing delete statements first, you should add / delete items to the collection instead of assigning a new collection, and configure the operations to cascade in the mapping data