拿Classes和Student为例。
package com.test; import java.util.Set; public class Classes { private Integer classesId; private String classesName; private Set students; public Set getStudents() { return students; } public void setStudents(Set students) { this.students = students; } public Integer getClassesId() { return classesId; } public void setClassesId(Integer classesId) { this.classesId = classesId; } public String getClassesName() { return classesName; } public void setClassesName(String classesName) { this.classesName = classesName; } }
package com.test; public class Student { private Integer studentId; private String studentName; public Integer getStudentId() { return studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } }
测试类:
public void testAdd(){ Session session = HibernateUtils.getSession(); session.beginTransaction(); Student student1 = new Student(); student1.setStudentName("zhangsan"); Student student2 = new Student(); student2.setStudentName("lisi"); Classes classes = new Classes(); classes.setClassesName("02-1"); Set students = new HashSet(); students.add(student1); students.add(student2); classes.setStudents(students); session.save(classes); session.getTransaction().commit(); HibernateUtils.closeSession(session); }
这时会报org.hibernate.TransientObjectException异常,说明save classes对象时,student1和student2还是游离态对象,但是因为是一对多关系,所以一方Classes要知道多方的信息,这时多方还是游离态,所以就报错了。 可以设置让 Student对象级联更新。如下:
执行的sql代码如下:
Hibernate: insert into classes (classes_name) values (?) Hibernate: insert into student (student_name) values (?) Hibernate: insert into student (student_name) values (?) Hibernate: update student set cls_id=? where student_id=? Hibernate: update student set cls_id=? where student_id=?
可以看出是先insert,再update.这样有个缺点:如果数据量很大时会严重影响效率。可以通过inverse标签反转下。
执行的sql如下:
Hibernate: insert into classes (classes_name) values (?) Hibernate: insert into student (student_name) values (?) Hibernate: insert into student (student_name) values (?)
但是这时数据库记录里外键的值是null. 所以还需要配置双向关联。
Studnet.hbm.xml里添加:
Student.java里添加:
private Classes classes; public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; }
测试类里添加:
classes.setStudents(students); student1.setClasses(classes); student2.setClasses(classes);
如果不设置级联更新,也可以这样:
Classes.hbm.xml
Student.hbm.xml不变:
测试类:
public void testAdd1(){ Session session = HibernateUtils.getSession(); session.beginTransaction(); Student student1 = new Student(); student1.setStudentName("zhangsan"); Student student2 = new Student(); student2.setStudentName("lisi"); Classes classes = new Classes(); classes.setClassesName("02-1"); student1.setClasses(classes); student2.setClasses(classes); session.save(classes); session.save(student1); session.save(student2); session.getTransaction().commit(); HibernateUtils.closeSession(session); }
执行sql:
Hibernate: insert into classes (classes_name) values (?) Hibernate: insert into student (student_name, cls_id) values (?, ?) Hibernate: insert into student (student_name, cls_id) values (?, ?)
总结:
1.都需要设置双向关联(指的是配置文件)
2.都需要设置inverse=true。(对级联来说,不用先insert,再update了)
3.设置了 cascade以后,save的是Classes对象,Student会级联保存。前提是双方关联:
classes.setStudents(students);
student1.setClasses(classes);
student2.setClasses(classes);
4.没有设置cascade的话,save的是Student对象。不过save Student对象以前,要先save Classes对象。