在一般情况下做关联映射的时候,很多人都喜欢用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
老猫也是新手,如果各位大神有任何异议或者更好的解析,小弟愿闻其详!