【学习笔记】Hibernate中多对多不用List而用Set的原因分析

在一般情况下做关联映射的时候,很多人都喜欢用List,我就是其中一个,毕竟query.list()返回的就是list对象,因此也用习惯了

但是今天发现在多对多的时候尽量不要用List,因为用list会导致复合主键问题。



场景:Teacher和Student是两个多对多关系的类,每个类有自己的id和name,代表学生和老师,还有一个集合,代表对应的关系(废话:一个学生可以有多个老师,一个老师可以有多个学生)

实体类就不说了,如果实体类还不懂的建议先去看懂普通实体类的映射


首先用List,List的映射文件代码如下:

Student.hbm.xml【List】

<hibernate-mapping package="g_hbm_manyToMany">

	<!-- 表对应的映射关系 -->
	<class name="Student" table="student">
		<id name="id">
			<generator class="native" />
		</id>
		<property column="name" name="name" type="string" />
		
		<!-- 
			Teacher属性,表达的是本类与Teacher的关系
			Table属性:中间表(集合表)
			key子元素:集合外键(引用当前表主键的外键),里面的Column指的是在中间表中的列名
			many-to-many子元素:里面的class属性是指关联的类型,column是指引用Teacher的主键值
		-->
		<list name="teacherList" table="teacher_student">
			<key column="studentId"></key><!-- 声明外键 -->
			<list-index column="idx"></list-index>
			<many-to-many class="Teacher" column="teacherId"></many-to-many>
		</list>		
				
	</class>
</hibernate-mapping>




Teacher.hbm.xml【List】

<hibernate-mapping package="g_hbm_manyToMany">

	<!-- 表对应的映射关系 -->
	<class name="Teacher" table="teacher">
		<id name="id">
			<generator class="native" />
		</id>
		<property column="name" name="name" type="string" />
		
		<!-- 
			Student属性,表达的是本类与Student的多对多关系
		-->
		<list name="studentList" table="teacher_student">
			<key column="teacherId"></key>
			<list-index column="idx"></list-index>
			<many-to-many class="Student" column="studentId"></many-to-many>
		</list>
		
				
	</class>
</hibernate-mapping>

从上面的映射文件可以看出,都有list-index这个子元素,指向相同的index列,然后我们通过hibernate自动生成表的方法操作一下


现在问题出来了:

原本两个表的关系表,应该是teacherId和studentId作为联合主键的,现在是idx是其中一个联合主键,虽然两个外键还是teacherId和studentId,但是其中一个主键竟然是idx,这就是冲突了,


虽然在插入数据的过程中不会对数据造成太大的影响,但是为了保险起见,我们还是用回Set作为集合的操作


用Set来作为集合映射:

Teacher.hbm.xml【Set】

<hibernate-mapping package="g_hbm_manyToMany">

	<!-- User表对应的映射关系 -->
	<class name="Teacher" table="teacher">
		<id name="id">
			<generator class="native" />
		</id>
		<property column="name" name="name" type="string" />
		
		<!-- 
			Student属性,表达的是本类与Student的多对多关系
		-->
		<set name="studentList" table="teacher_student">
			<key column="teacherId"></key>
			<many-to-many class="Student" column="studentId"></many-to-many>
		</set>
		
				
	</class>
</hibernate-mapping>



Student.hbm.xml【Set】

<hibernate-mapping package="g_hbm_manyToMany">

	<!-- User表对应的映射关系 -->
	<class name="Student" table="student">
		<id name="id">
			<generator class="native" />
		</id>
		<property column="name" name="name" type="string" />
		
		<!-- 
			Teacher属性,表达的是本类与Teacher的关系
			Table属性:中间表(集合表)
			key子元素:集合外键(引用当前表主键的外键),里面的Column指的是在中间表中的列名
			many-to-many子元素:里面的class属性是指关联的类型,column是指引用Teacher的主键值
		-->
		<set name="teacherList" table="teacher_student">
			<key column="studentId"></key><!-- 声明外键 -->
			<many-to-many class="Teacher" column="teacherId"></many-to-many>
		</set>		
				
	</class>
</hibernate-mapping>


用hibernate执行生成表:





从这里可以看出,为了避免不必要的错误,多对多关系的情况下尽量使用Set


老猫也是新手,如果各位大神有任何异议或者更好的解析,小弟愿闻其详!






你可能感兴趣的:(Hibernate,list,set,学习笔记,多对多)