Hibernate学习之路(八):双向多对多映射

hibernate如何处理双向多对多映射关系的?
  • 双向 n-n 关联需要两端都使用集合属性

  • 双向n-n关联必须使用连接表(即第三方表)

  • 集合属性应增加 key 子元素用以映射外键列, 还应增加many-to-many子元素关联实体类
    在双向 n-n 关联的两边都需指定连接表的表名及外键列的列名. 两个集合元素 set 的 table 元素的值必须指定,而且必须相同。
    set元素的两个子元素:key 和 many-to-many 都必须指定 column 属性,其中,key 和 many-to-many 分别指定本持久化类和关联类在连接表中的外键列名,因此两边的 key 与 many-to-many 的column属性交叉相同。也就是说,一边的set元素的key的 cloumn值为a,many-to-many 的 column 为b;则另一边的 set 元素的 key 的 column 值 b,many-to-many的 column 值为 a.
  • 对于双向 n-n 关联, 必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突.

  • 解释代码如下:

Student.java

public class Student {

    private Integer id;
    private String name;

    private Set<Course> courses = new HashSet<>();

    //...   
}

Course.java

public class Course {
    private Integer id;
    private String name;
    private Set<Student> students = new 
    HashSet<>();

    //...
}

Course.hbm.xml

<hibernate-mapping package="com.zc.cris.manytomany">
    <class name="Course" table="COURSE">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String" >
            <column name="NAME" />
        </property>

       <!-- 映射多对多的关系,需要指定一张中间表,并且需要有一方放弃关系维护 -->
       <set name="students" table="STUDENT_COURSE" inverse="true">
            <key>
                <!-- 指定当前对象在中间表的列名 -->
                <column name="COURSE_ID"></column>
            </key>
            <!-- 多对多关系映射,column指定set集合中的持久化类在中间表的名称 -->
            <many-to-many class="Student" column="STUDENT_ID"></many-to-many>
       </set>

    </class>
</hibernate-mapping>

Student.hbm.xml

<hibernate-mapping package="com.zc.cris.manytomany">

    <class name="com.zc.cris.manytomany.Student" table="STUDENTS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>

        <set name="courses" table="STUDENT_COURSE">
            <key>
                <!-- 指定当前对象在中间表的列名 -->
                <column name="STUDENT_ID"></column>
            </key>
            <!-- 多对多关系映射,column指定set集合中的持久化类在中间表的外键的名称 -->
            <many-to-many class="Course" column="COURSE_ID"></many-to-many>
        </set>


    </class>
</hibernate-mapping>

TestHibernate.java

@Test
    void testGet() {
        //同样存在懒加载问题
        Student student = this.session.get(Student.class, 1);
        System.out.println(student.getName());
        System.out.println(student.getCourses().getClass());
//      select
//          courses0_.STUDENT_ID as STUDENT_2_1_0_,
//          courses0_.COURSE_ID as COURSE_I1_1_0_,
//          course1_.ID as ID1_0_1_,
//          course1_.NAME as NAME2_0_1_ 
//              from
//                  STUDENT_COURSE courses0_ 
//              inner join
//                  COURSE course1_ 
//                      on courses0_.COURSE_ID=course1_.ID 
//              where
//                  courses0_.STUDENT_ID=?
        System.out.println(student.getCourses().size());

    }

    @Test
    void testSave() {
        Student student1 = new Student();
        Student student2 = new Student();
        student1.setName("a");
        student2.setName("b");

        Course course1 = new Course();
        Course course2 = new Course();
        course1.setName("aa");
        course2.setName("bb");

        course1.getStudents().add(student1);
        course1.getStudents().add(student2);
        course2.getStudents().add(student1);
        course2.getStudents().add(student2);

        student1.getCourses().add(course1);
        student1.getCourses().add(course2);
        student2.getCourses().add(course1);
        student2.getCourses().add(course1);

        this.session.save(student1);
        this.session.save(student2);
        this.session.save(course1);
        this.session.save(course2);
    }

测试结果如图:

image

image

image

点我获取源代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值