• hibernate多表操作


    一、表之间的关系

      1.一对一

      2.一对多

      3.多对多

    二、表之间关系建表原则

      1.一对多:在多的一方创建一个外键,指向一的一方的主键

      

      2.多对多:创建一个中间表,中间表至少有两个字段,分别作为外键指向多对多双方的主键

      

    3.一对一:主键一一对应,或当成一对多来看待。

    三、一对多实现

      1)定义

    1.在1的domain类中定义:

    private Set<link> links= new HashSet<>();
    在相应映射配置文件中:
    <!--一对多-->
    <set name="links"><!--set属性名称-->
        <key column="link_cust_id"></key><!--外键-->
        <one-to-many class="com.ual.domain.link"></one-to-many>
    </set>

    如果想要保存记录的时候保存其级联的记录,需要在set 后添加

    cascade="save-update"

    2.在多的domain类中定义:

        //一个联系人只对应一个客户
        private  customer customer;

    在相应映射配置文件中:

    <many-to-one name="customer" class="com.ual.domain.customer" column="link_cust_id" insert="false" update="false" lazy="false"></many-to-one>

    加入lazy="false"后,在查询时会把记录相关的外键对应的记录一起查询出来。

    3.在核心配置文件中,把映射关系写入

    <mapping resource="com/ual/domain/customer.hbm.xml"/><!--告诉hibernate要操作哪些表,写入映射的配置文件的全路径-->
            <mapping resource="com/ual/domain/link.hbm.xml"></mapping>

    4.实现插入

    @Test
        public void test(){
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            customer c1 = new customer();
            c1.setCust_name("c1");
            customer c2= new customer();
            c2.setCust_name("c2");
            link link1 = new link();
            link1.setLink_name("link1");
            link link2 = new link();
            link2.setLink_name("link2");
            link link3 = new link();
            link3.setLink_name("link3");
            /*配置关系*/
            c1.getLinks().add(link1);
            c1.getLinks().add(link3);
            c2.getLinks().add(link2);
            link1.setCustomer(c1);
            link2.setCustomer(c2);
            link3.setCustomer(c1);
            /*保存联系人*/
            session.save(c1);
            session.save(c2);
            session.save(link1);
            session.save(link2);
            session.save(link3);
    
            transaction.commit();
        }

    配置关系时,一般使用双向维护

    2)查询

        @Test
        public void test2(){
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            link link=session.get(com.ual.domain.link.class,6L);
            transaction.commit();
            System.out.println(link.getLink_name());
            System.out.println(link.getCustomer().getCust_name());
        }

    注:

    级联操作:

      1.问题:在两张表建立一对多关系时,如果只保存一边的对象,会引发异常

      2.级联操作:

        什么时级联操作:在操作一个对象时,是否会操作其关联的对象

        级联分类:  

          级联保存或更新:cascade="save-update"

          级联删除:cascade="delete,save-update"

        级联是有方向性的:保存的是谁就到谁里面做级联,删除的是谁就到谁里面做级联

    3)更新

      

       @Test
        public void test4(){
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //更新
            link link=session.get(link.class,10L);
            customer customer=session.get(com.ual.domain.customer.class,13L);
            //10本来关联12,现让其关联13
            //双向维护
            customer.getLinks().add(link);
            link.setCustomer(customer);
            session.update(customer);
            transaction.commit();
        }

    注: 由于使用的双向维护,两方同时去维护一个外键,会产生性能问题,可以让一方放弃维护外键,只让外键所在的表维护外键

      需要配置:在1的配置文件中:加inverse="true"

    四、多对多关系实现

    1、表关系:用户角色表

    2、多对多映射文件配置

    role:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!--让java中的类与数据库中的表相关联,这样操作domain类就操作了与该类映射的表-->
    <hibernate-mapping>
        <class name="com.ual.domain.role" table="role"><!--name对应类中,table对应表中-->
            <!--建立类属性,哪一个是主键,该主键需要跟数据库中的主键相对应-->
            <id name="r_id" column="r_id"><!--name对应类,column对应表-->
                 <generator class="native"/><!--主键生成策略-->
            </id>
            <!--建立类中的普通属性和数据库中的字段进行关联-->
            <property name="r_name" column="r_name"/>
            <!--多对多-->
            <set name="users" table="role_user">
                <key column="r_id"></key>
                <many-to-many class="com.ual.domain.user" column="u_id"></many-to-many>
            </set>
        </class>
    
    </hibernate-mapping>

    user:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!--让java中的类与数据库中的表相关联,这样操作domain类就操作了与该类映射的表-->
    <hibernate-mapping>
        <class name="com.ual.domain.user" table="user"><!--name对应类中,table对应表中-->
            <!--建立类属性,哪一个是主键,该主键需要跟数据库中的主键相对应-->
            <id name="u_id" column="u_id"><!--name对应类,column对应表-->
                 <generator class="native"/><!--主键生成策略-->
            </id>
            <!--建立类中的普通属性和数据库中的字段进行关联-->
            <property name="u_name" column="u_name"/>
            <!--多对多
            name: 当前类下集合属性的名称
            table:多对多中间表的表名
            column:当前表的外键
            <many-to-many class="" column=""></many-to-many>
            class:当前类集合中对象的全路径
            column:集合中对象的外键
            -->
            <set name="roles" table="role_user">
                <key column="u_id"></key>
                <many-to-many class="com.ual.domain.role" column="r_id"></many-to-many>
            </set>
        </class>
    
    </hibernate-mapping>

    3、配置核心配置文件

    <mapping resource="com/ual/domain/role.hbm.xml"></mapping>
            <mapping resource="com/ual/domain/user.hbm.xml"></mapping>

    4、插入数据测试

     @Test
        public void test(){
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //创建用户
            user user1 = new user();
            user1.setU_name("user1");
            user user2 = new user();
            user2.setU_name("user2");
            //创建角色
            role role1 = new role();
            role1.setR_name("role1");
            role role2 = new role();
            role role3 = new role();
            role2.setR_name("role2");
            role3.setR_name("role3");
    
            //配置关系
            user1.getRoles().add(role1);
            user1.getRoles().add(role2);
            user2.getRoles().add(role1);
            user2.getRoles().add(role3);
    
            role1.getUsers().add(user1);
            role1.getUsers().add(user2);
            role2.getUsers().add(user1);
            role3.getUsers().add(user2);
            //保存
            session.save(user1);
            session.save(user2);
            
            transaction.commit();
        }

    注意:在多对多建表时,使用双向维护,必须要使得一方放弃外键维护权,一般在被选择一方放弃外键维护,如角色被用户选择,让角色放弃外键维护权。否则,报外键重复异常。 

        

    <set name="users" table="role_user" inverse="true" >
                <key column="r_id"></key>
                <many-to-many class="com.ual.domain.user" column="u_id" ></many-to-many>
            </set>

    5、其他数据操作

       @Test
        public void test2(){
            //关系操作 就是操作内部集合
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //给用户1添加角色3
            user user = session.get(user.class, 1L);
            role role = session.get(role.class, 3L);
            user.getRoles().add(role);
            transaction.commit();
        }
      @Test
        public void test3(){
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //更改,把用户2的角色3 修改为2
            user user2 = session.get(user.class, 2L);
            role role3 = session.get(role.class, 3L);
            role role2 = session.get(role.class, 2L);
             user2.getRoles().remove(role3);
             user2.getRoles().add(role2);
            transaction.commit();
        }
  • 相关阅读:
    SINAMICS S120/S120 EPOS 基本定位修改方向
    西门子 SINAMICS S120 Web server 用户名和默认密码
    在windows bat脚本(batch)中延时
    ubuntu修改字体大小
    python从字符串中提取数字,使用正则表达式
    python读入文档中的一行
    C++控制台暂停
    在ubuntu linux下安装*.sh的方法
    anaconda和jupyter notebook使用方法
    word禁止自动编号
  • 原文地址:https://www.cnblogs.com/UalBlog/p/10604573.html
Copyright © 2020-2023  润新知