hibernate一对多关联关系

想了几天,终于知道sql语句的发出问题。查了很多书,感觉都没有说清楚,有的还是错的。请看下面:

<?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的这个对象(我以前一直是这样理解的,后来发现我错了)。

原文地址:https://www.cnblogs.com/dyllove98/p/3141303.html