<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" cascade="save-update">
<!--
<key column="classesid" not-null="true"/>
-->
<key column="classesid"/>
<one-to-many class="com.bjpowernode.hibernate.Student"/>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="classes" column="classesid" cascade="save-update"/>
</class>
</hibernate-mapping>
测试的语句:
session = HibernateUtils.getSession();
session.beginTransaction();
Student student1 = new Student();
student1.setName("张三");
Classes classes = new Classes();
classes.setName("动力节点");
student1.setClasses(classes);
//Set students = new HashSet();
//students.add(student1);
classes.getStudents().add(student1);
//抛出TransientObjectException
//因为Student不是Persistent状态的对象,它是Transient状态的对象
session.save(classes);
Hibernate: insert into t_classes (name) values (?)
Hibernate: insert into t_student (name, classesid) values (?, ?)
Hibernate: update t_student set classesid=? where id=?
问题一:既然是两端维持关系,为什么不发出
Hibernate: insert into t_classes (name) values (?)
Hibernate: insert into t_student (name, classesid) values (?, ?)
而是发出三条语句呢?
答:我猜想内部机制,当它发现session.save(classes)时,也就是保存一的一端的时候,他会使用一的一端来维持关系,这时候student1.setClasses(classes);这句话就不管了。所以此时Hibernate: insert into t_student (name, classesid) values (?, ?)中的那个字段还是为空。它看不到关系。(孙卫琴老师的精通hibernate这本书这个地方说发出两条sql语句是错误的)
当保存多的一端的时候,他会使用多的一端来维持关系,这时候classes.getStudents().add(student1);这句话就不管了。此时它能够看到student1.setClasses(classes);所以保存Hibernate: insert into t_student (name, classesid) values (?, ?)中的那个字段不会为空。它能够看到关系。
总结一句话:保存一的一端会发出多条update的语句。而保存多的一端不会发出多条update的语句(尽管是两端维持关系,但是会只用一端控制机制)。
问题二:级联保存的时候,是先保存多的一端还是先保存一的一端呢?
答:不管是session.save(classes);还是session.save(students);一定是先保存一的一端,再保存多的一端。而不是先保存级联的那个对象,再保存save的这个对象(我以前一直是这样理解的,后来发现我错了)。