zoukankan      html  css  js  c++  java
  • hibernate的多对多关联映射

      

      在我们实际项目中,多对多的情况也时长存在,比如最常见的就是系统管理的五张表,如下面的一个结构:

    在本文学习hibernate多对多关联映射的实验中我简单的写几个字段,达到学习目的即可。

    1.多对多的关系表达

    1.关系型数据库(RDB)中的表达:

     2.Java实体中的表达

     

     

     3.orm配置文件中的表达:(注意每次添加了ORM映射文件都要加到主配置文件中)

     User.hbm.xml

    <?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">
       <!-- 配置表与实体对象的关系 -->
       <!-- package属性:填写一个包名.在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了. -->
    <hibernate-mapping package="cn.qlq.domain" >
        <!-- 
            class元素: 配置实体与表的对应关系的
                name: 完整类名
                table:数据库表名
         -->
        <class name="User" table="sys_user" >
            <!-- id元素:配置主键映射的属性
                    name: 填写主键对应属性名
                    column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
                    type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
                            每个类型有三种填法: java类型|hibernate类型|数据库类型
                    not-null(可选):配置该属性(列)是否不能为空. 默认值:false
                    length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
             -->
            <id name="user_id"  >
                <!-- generator:主键生成策略 -->
                <!--identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.  -->
                <generator class="native"></generator>
            </id>
            <!-- property元素:除id之外的普通属性映射
                    name: 填写属性名
                    column(可选): 填写列名
                    type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
                            每个类型有三种填法: java类型|hibernate类型|数据库类型
                    not-null(可选):配置该属性(列)是否不能为空. 默认值:false
                    length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
             -->
            <property name="User_name" length="20"/>
            <property name="user_state"/>
        
            <!-- 集合,多对多关系,在配置文件中配置 -->
            <!--  
                name:集合属性名字
                table:中间表名
            -->
            <set name="roles" table="sys_user_role">
                <!-- column:外键,别人引用我的外键列名 -->
                <key column="user_id" ></key>
                <!-- class:我与哪个表是多对多关系,column:外键,我引用别人的外键 -->
                <many-to-many class="Role" column="role_id"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

     Role.hbm.xml

    <?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">
       <!-- 配置表与实体对象的关系 -->
       <!-- package属性:填写一个包名.在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了. -->
    <hibernate-mapping package="cn.qlq.domain" >
        <!-- 
            class元素: 配置实体与表的对应关系的
                name: 完整类名
                table:数据库表名
         -->
        <class name="Role" table="sys_role" >
            <!-- id元素:配置主键映射的属性
                    name: 填写主键对应属性名
                    column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
                    type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
                            每个类型有三种填法: java类型|hibernate类型|数据库类型
                    not-null(可选):配置该属性(列)是否不能为空. 默认值:false
                    length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
             -->
            <id name="role_id"  >
                <!-- generator:主键生成策略 -->
                <!--identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.  -->
                <generator class="native"></generator>
            </id>
            <!-- property元素:除id之外的普通属性映射
                    name: 填写属性名
                    column(可选): 填写列名
                    type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
                            每个类型有三种填法: java类型|hibernate类型|数据库类型
                    not-null(可选):配置该属性(列)是否不能为空. 默认值:false
                    length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
             -->
            <property name="role_name" length="20"/>
            <property name="role_state"/>
        
            <!-- 集合,多对多关系,在配置文件中配置 -->
            <!--  
                name:集合属性名字
                table:中间表名
            -->
            <set name="users" table="sys_user_role">
                <!-- column:外键,别人引用我的外键列名 -->
                <key column="role_id" ></key>
                <!-- class:我与哪个表是多对多关系,column:外键,我引用别人的外键 -->
                <many-to-many class="User" column="user_id"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

     4.测试建表结果:

         随便执行一个hibernate测试,会加载主配置文件并进行建表。

    mysql> desc sys_user;
    +------------+-------------+------+-----+---------+----------------+
    | Field      | Type        | Null | Key | Default | Extra          |
    +------------+-------------+------+-----+---------+----------------+
    | user_id    | bigint(20)  | NO   | PRI | NULL    | auto_increment |
    | User_name  | varchar(20) | YES  |     | NULL    |                |
    | user_state | char(1)     | YES  |     | NULL    |                |
    +------------+-------------+------+-----+---------+----------------+
    3 rows in set (0.00 sec)
    
    mysql> desc sys_role;
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | role_id    | bigint(20)   | NO   | PRI | NULL    | auto_increment |
    | role_name  | varchar(20)  | YES  |     | NULL    |                |
    | role_state | varchar(255) | YES  |     | NULL    |                |
    +------------+--------------+------+-----+---------+----------------+
    3 rows in set (0.00 sec)
    
    mysql> desc sys_user_role;
    +---------+------------+------+-----+---------+-------+
    | Field   | Type       | Null | Key | Default | Extra |
    +---------+------------+------+-----+---------+-------+
    | user_id | bigint(20) | NO   | PRI | NULL    |       |
    | role_id | bigint(20) | NO   | PRI | NULL    |       |
    +---------+------------+------+-----+---------+-------+
    2 rows in set (0.00 sec)

     5.修改ORM配置中set元素配置对set元素的进一步解释

     User.hbm.xml

     Role.hbm.xml

     修改之后查看建表语句:

    mysql> show create table sys_user_roleG
    *************************** 1. row ***************************
           Table: sys_user_role
    Create Table: CREATE TABLE `sys_user_role` (
      `user_id1` bigint(20) NOT NULL,
      `role_id1` bigint(20) NOT NULL,
      PRIMARY KEY (`role_id1`,`user_id1`),
      KEY `FKgxeccay1ha1igqs2myct720lt` (`user_id1`),
      CONSTRAINT `FKgxeccay1ha1igqs2myct720lt` FOREIGN KEY (`user_id1`) REFERENCES `sys_user` (`user_id`)
      CONSTRAINT `FKtfvi95hnfedqqxi3rk1qmrwy7` FOREIGN KEY (`role_id1`) REFERENCES `sys_role` (`role_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    1 row in set (0.00 sec)

     总结:

            <set name="users" table="sys_user_role">
                <!-- column:外键,别人引用我的外键列名 (可以简单的理解为中间表的列名)-->
                <key column="role_id1" ></key>
                <!-- class:我与哪个表是多对多关系,column:外键,我引用别人的外键 -->
                <many-to-many class="User" column="user_id1"></many-to-many>
            </set>

      个人认为set元素更像是配置我与中间表的关系,key元素可以理解为中间表指向我的外键的名字,

        many-to-many中的class指的是与我是多对多的对象类名,column是在中间表中其对应的外键名字。

    2.多对多操作

    --------------------------第一次测试-----------------

    1.测试保存:

        /**
         *测试保存(多对多)
         */
        @Test
        public void fun1() {
            //1.获取session
            Session session = HibernateUtil.openSession();
            //2.开启事务
            Transaction tx = session.beginTransaction();
            //3.构造数据(张三-总监、经理,李四---总监)
            User u1 = new User();
            u1.setUser_name("张三");
            User u2 = new User();
            u2.setUser_name("李四");
            
            Role r1 = new Role();
            r1.setRole_name("总监");
            Role r2 = new Role();
            r2.setRole_name("经理");
            
            u1.getRoles().add(r1);
            u1.getRoles().add(r2);
            u2.getRoles().add(r1);
            r1.getUsers().add(u1);
            r1.getUsers().add(u2);
            r2.getUsers().add(u1);
            
            session.save(u1);
            session.save(u2);
            session.save(r1);
            session.save(r1);
            //4.提交数据
            tx.commit();
            //5.关闭session
            session.close();
        }

     执行会报错,因为两个表都维护关系,所以会像中间表插入两次记录,导致插入重复。如下错误:

     解决办法:

    •   第一钟:将一方维护关系的代码注释掉:(一般开发中多对多的关系中都有一方放弃维护关系)

          

    • 第二种:配置文件中,设置一方放弃维护关系,例如:设置user放弃维护关系(一般开发中多对多的关系中都有一方放弃维护关系)

        

    2.测试修改:

        /**
         *新增一个角色,并给张三新增加一个角色
         */
        @Test
        public void fun2() {
            //1.获取session
            Session session = HibernateUtil.openSession();
            //2.开启事务
            Transaction tx = session.beginTransaction();
            //3.构造数据(张三-总监、经理,李四---总监)
            User u1 = session.get(User.class, 1l);
            Role r3 = new Role();
            r3.setRole_name("太监");
            
            session.save(r3);//保存新角色
            
            u1.getRoles().add(r3);//u1处于持久态,因此不用执行更新语句也可以更新
    
            //4.提交数据
            tx.commit();
            //5.关闭session
            session.close();
        }

     3.测试给张三删除一个角色

        /**
         *为张三删除一个太监角色
         */
        @Test
        public void fun3() {
            //1.获取session
            Session session = HibernateUtil.openSession();
            //2.开启事务
            Transaction tx = session.beginTransaction();
            //3.构造数据(张三-总监、经理,李四---总监)
            User u1 = session.get(User.class, 1l);
            Role r1 = session.get(Role.class, 3l);
            
            
            u1.getRoles().remove(r1);//u1处于持久态,因此不用执行更新语句也可以更新
    
            //4.提交数据
            tx.commit();
            //5.关闭session
            session.close();
        }

     查看发出的SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.User_name as User_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        select
            role0_.role_id as role_id1_2_0_,
            role0_.role_name as role_nam2_2_0_,
            role0_.role_state as role_sta3_2_0_ 
        from
            sys_role role0_ 
        where
            role0_.role_id=?
    Hibernate: 
        select
            roles0_.user_id as user_id1_4_0_,
            roles0_.role_id as role_id2_4_0_,
            role1_.role_id as role_id1_2_1_,
            role1_.role_name as role_nam2_2_1_,
            role1_.role_state as role_sta3_2_1_ 
        from
            sys_user_role roles0_ 
        inner join
            sys_role role1_ 
                on roles0_.role_id=role1_.role_id 
        where
            roles0_.user_id=?
    Hibernate: 
        delete 
        from
            sys_user_role 
        where
            user_id=? 
            and role_id=?

    ---------------------------第二次测试------------------

    1.添加一个张三用户,并给其添加两个角色:经理和总监

        /**
         * 测试1:添加一个张三用户
         * 添加两个角色:经理、总监
         */
        @Test
        public void test1(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            
            /******S  开始业务逻辑*************/
            User u1 = new User();
            u1.setUser_name("张三");
            
            Role r1 = new Role();
            Role r2 = new Role();
            r1.setRole_name("总监");
            r2.setRole_name("经理");
            
            u1.getRoles().add(r1);
            u1.getRoles().add(r2);
            
            session.save(u1);
            session.save(r1);
            session.save(r2);
            /******E  开始业务逻辑*************/
            
            tx.commit();
            
        }

    SQL:

    Hibernate: 
        insert 
        into
            sys_user
            (user_name, user_state) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            sys_role
            (role_name, role_state) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            sys_role
            (role_name, role_state) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            sys_user_role
            (user_id, role_id) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            sys_user_role
            (user_id, role_id) 
        values
            (?, ?)

    结果:

    mysql> select * from sys_user;
    +---------+-----------+------------+
    | user_id | user_name | user_state |
    +---------+-----------+------------+
    |       1 | 张三      | NULL       |
    +---------+-----------+------------+
    1 row in set (0.03 sec)
    
    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    |       2 | 经理      | NULL       |
    +---------+-----------+------------+
    2 rows in set (0.00 sec)
    
    mysql> select * from sys_user_role;
    +---------+---------+
    | user_id | role_id |
    +---------+---------+
    |       1 |       1 |
    |       1 |       2 |
    +---------+---------+
    2 rows in set (0.00 sec)

    2.给上面的张三解除与总监角色的关联关系

        /**
         * 测试2:给上面的张三解除与总监角色的关联关系
         */
        @Test
        public void test2(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            
            /******S  开始业务逻辑*************/
            //get方法获取的对象都是持久态
            User user = session.get(User.class,1l );
            Role role = session.get(Role.class, 1l);
            user.getRoles().remove(role);
            /******E  开始业务逻辑*************/
            
            tx.commit();
        }

    SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.user_name as user_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        select
            role0_.role_id as role_id1_2_0_,
            role0_.role_name as role_nam2_2_0_,
            role0_.role_state as role_sta3_2_0_ 
        from
            sys_role role0_ 
        where
            role0_.role_id=?
    Hibernate: 
        select
            roles0_.user_id as user_id1_4_0_,
            roles0_.role_id as role_id2_4_0_,
            role1_.role_id as role_id1_2_1_,
            role1_.role_name as role_nam2_2_1_,
            role1_.role_state as role_sta3_2_1_ 
        from
            sys_user_role roles0_ 
        inner join
            sys_role role1_ 
                on roles0_.role_id=role1_.role_id 
        where
            roles0_.user_id=?
    Hibernate: 
        delete 
        from
            sys_user_role 
        where
            user_id=? 
            and role_id=?

    结果:

    mysql> select * from sys_user;
    +---------+-----------+------------+
    | user_id | user_name | user_state |
    +---------+-----------+------------+
    |       1 | 张三      | NULL       |
    +---------+-----------+------------+
    1 row in set (0.00 sec)
    
    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    |       2 | 经理      | NULL       |
    +---------+-----------+------------+
    2 rows in set (0.00 sec)
    
    mysql> select * from sys_user_role;
    +---------+---------+
    | user_id | role_id |
    +---------+---------+
    |       1 |       2 |
    +---------+---------+
    1 row in set (0.00 sec)

    3.删除经理角色,同时删除与张三的绑定关系

        /**
         * 测试3:删除经理角色,同时删除与张三的绑定关系
         */
        @Test
        public void test3(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            
            /******S  开始业务逻辑*************/
            //get方法获取的对象都是持久态
            User user = session.get(User.class,1l );
            Role role = session.get(Role.class, 2l);
            session.delete(role);
            /******E  开始业务逻辑*************/
            
            tx.commit();
        }

    SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.user_name as user_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        select
            role0_.role_id as role_id1_2_0_,
            role0_.role_name as role_nam2_2_0_,
            role0_.role_state as role_sta3_2_0_ 
        from
            sys_role role0_ 
        where
            role0_.role_id=?
    Hibernate: 
        delete 
        from
            sys_user_role 
        where
            role_id=?
    Hibernate: 
        delete 
        from
            sys_role 
        where
            role_id=?

    结果:

    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    +---------+-----------+------------+
    1 row in set (0.00 sec)
    
    mysql> select * from sys_user_role;
    Empty set (0.00 sec)

    4.新增一个秘书角色,并赋给张三该角色

        /**
         * 测试4:新增一个秘书角色,并赋给张三该角色
         */
        @Test
        public void test4(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            
            /******S  开始业务逻辑*************/
            //get方法获取的对象都是持久态
            Role r1 = new Role();
            r1.setRole_name("秘书");
            User user = session.get(User.class,1l);
            user.getRoles().add(r1);
            
            session.save(r1);
            session.update(user);
            /******E  开始业务逻辑*************/
            
            tx.commit();
        }

    SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.user_name as user_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        select
            roles0_.user_id as user_id1_4_0_,
            roles0_.role_id as role_id2_4_0_,
            role1_.role_id as role_id1_2_1_,
            role1_.role_name as role_nam2_2_1_,
            role1_.role_state as role_sta3_2_1_ 
        from
            sys_user_role roles0_ 
        inner join
            sys_role role1_ 
                on roles0_.role_id=role1_.role_id 
        where
            roles0_.user_id=?
    Hibernate: 
        insert 
        into
            sys_role
            (role_name, role_state) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            sys_user_role
            (user_id, role_id) 
        values
            (?, ?)

    结果:

    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    |       3 | 秘书      | NULL       |
    +---------+-----------+------------+
    2 rows in set (0.00 sec)
    
    mysql> select * from sys_user_role;
    +---------+---------+
    | user_id | role_id |
    +---------+---------+
    |       1 |       3 |
    +---------+---------+
    1 row in set (0.00 sec)

    5.修改秘书角色为总监秘书(不影响与用户的关联)

        /**
         * 测试5:修改秘书角色为总监秘书(不影响与用户的关联)
         */
        @Test
        public void test5(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
            
            /******S  开始业务逻辑*************/
            //get方法获取的对象都是持久态
            Role role = session.get(Role.class,3l);
            role.setRole_name("总监秘书");
            session.update(role);
            /******E  开始业务逻辑*************/
            
            tx.commit();
        }

    SQL:

    Hibernate: 
        select
            role0_.role_id as role_id1_2_0_,
            role0_.role_name as role_nam2_2_0_,
            role0_.role_state as role_sta3_2_0_ 
        from
            sys_role role0_ 
        where
            role0_.role_id=?
    Hibernate: 
        update
            sys_role 
        set
            role_name=?,
            role_state=? 
        where
            role_id=?

    结果:

    mysql> select * from sys_user_role;
    +---------+---------+
    | user_id | role_id |
    +---------+---------+
    |       1 |       3 |
    +---------+---------+
    1 row in set (0.00 sec)
    
    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    |       3 | 总监秘书  | NULL       |
    +---------+-----------+------------+
    2 rows in set (0.00 sec)

    6.删除一个用户,会自动删除中间表

    mysql> select * from sys_user_role;
    +---------+---------+
    | user_id | role_id |
    +---------+---------+
    |       1 |       3 |
    +---------+---------+
    1 row in set (0.00 sec)
    
    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    |       3 | 总监秘书  | NULL       |
    +---------+-----------+------------+
    2 rows in set (0.00 sec)

    SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.user_name as user_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        delete 
        from
            sys_user_role 
        where
            user_id=?
    Hibernate: 
        delete 
        from
            sys_user 
        where
            user_id=?

    结果:

    mysql> select * from sys_user;
    Empty set (0.00 sec)
    
    mysql> select * from sys_role;
    +---------+-----------+------------+
    | role_id | role_name | role_state |
    +---------+-----------+------------+
    |       1 | 总监      | NULL       |
    |       3 | 总监秘书  | NULL       |
    +---------+-----------+------------+
    2 rows in set (0.00 sec)
    
    mysql> select * from sys_user_role;
    Empty set (0.00 sec)

    3.进阶操作

    1.inverse属性:

       一般开发中遇到多对多的关系总有一方放弃维护关系,至于是哪一方要看具体的业务需求。可以在代码中放弃维护,也可以在配置文件中放弃维护。例如录入员工时需要为员工指定所属角色,那么业务方向就是由员工维护角色,角色不需要维护与员工的关系。

    • 代码中放弃维护角色:
        /**
         *测试保存(多对多)
         */
        @Test
        public void fun1() {
            //1.获取session
            Session session = HibernateUtil.openSession();
           //2.开启事务
            Transaction tx = session.beginTransaction();
            //3.构造数据(张三-总监、经理,李四---总监)
            User u1 = new User();
            u1.setUser_name("张三");
            User u2 = new User();
            u2.setUser_name("李四");
            
            Role r1 = new Role();
            r1.setRole_name("总监");
            Role r2 = new Role();
            r2.setRole_name("经理");
            
            u1.getRoles().add(r1);
            u1.getRoles().add(r2);
            u2.getRoles().add(r1);
            //角色放弃维护与员工的关系
    //        r1.getUsers().add(u1);
    //        r1.getUsers().add(u2);
    //        r2.getUsers().add(u1);
            
            session.save(r1);
            session.save(r2);
            session.save(u1);
            session.save(u2);
            //4.提交数据
            tx.commit();
            //5.关闭session
            session.close();
        }
    • Role.hbm.xml配置文件中放弃维护关系inverse属性为true即是放弃维护关系

    2.级联操作  cascade属性

    save-update :级联保存或更新

    delete:级联删除

    all:等于save-update+delete

    1.级联保存或者更新:

      例如我们新增一个角色并且给张三赋予新角色的代码如下:

        @Test
        public void fun2() {
            //1.获取session
            Session session = HibernateUtil.openSession();
            //2.开启事务
            Transaction tx = session.beginTransaction();
            //3.构造数据(张三-总监、经理,李四---总监)
            User u1 = session.get(User.class, 1l);
            Role r3 = new Role();
            r3.setRole_name("太监222");
            
            session.save(r3);//保存新角色
            
            u1.getRoles().add(r3);//u1处于持久态,因此不用执行更新语句也可以更新
    
            //4.提交数据
            tx.commit();
            //5.关闭session
            session.close();
        }

     

     我们希望在更新user的时候会级联保存角色,也就是省区一行session.save(r3)对象。

    (1)修改User.hbm.xml

     (2)将代码保存角色的那一行代码注释掉

    (3)测试并查看SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.User_name as User_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        select
            roles0_.user_id as user_id1_4_0_,
            roles0_.role_id as role_id2_4_0_,
            role1_.role_id as role_id1_2_1_,
            role1_.role_name as role_nam2_2_1_,
            role1_.role_state as role_sta3_2_1_ 
        from
            sys_user_role roles0_ 
        inner join
            sys_role role1_ 
                on roles0_.role_id=role1_.role_id 
        where
            roles0_.user_id=?
    Hibernate: 
        insert 
        into
            sys_role
            (role_name, role_state) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            sys_user_role
            (user_id, role_id) 
        values
            (?, ?)

    2.级联删除:

    修改User.hbm.xml,开启级联删除:

     

    测试代码:(会级联去删除角色表,如果角色表对应记录被其他用户引用会报错)

        /**
         *删除张三,查看级联删除角色
         */
        @Test
        public void fun4() {
            //1.获取session
            Session session = HibernateUtil.openSession();
            //2.开启事务
            Transaction tx = session.beginTransaction();
            //3.构造数据(张三-总监、经理,李四---总监)
            User u1 = session.get(User.class, 5l);
            session.delete(u1);
            
            //4.提交数据
            tx.commit();
            //5.关闭session
            session.close();
        }

    查看发出的SQL:

    Hibernate: 
        select
            user0_.user_id as user_id1_3_0_,
            user0_.User_name as User_nam2_3_0_,
            user0_.user_state as user_sta3_3_0_ 
        from
            sys_user user0_ 
        where
            user0_.user_id=?
    Hibernate: 
        select
            roles0_.user_id as user_id1_4_0_,
            roles0_.role_id as role_id2_4_0_,
            role1_.role_id as role_id1_2_1_,
            role1_.role_name as role_nam2_2_1_,
            role1_.role_state as role_sta3_2_1_ 
        from
            sys_user_role roles0_ 
        inner join
            sys_role role1_ 
                on roles0_.role_id=role1_.role_id 
        where
            roles0_.user_id=?
    Hibernate: 
        delete 
        from
            sys_user_role 
        where
            user_id=?
    Hibernate: 
        delete 
        from
            sys_role 
        where
            role_id=?
    Hibernate: 
        delete 
        from
            sys_role 
        where
            role_id=?
    Hibernate: 
        delete 
        from
            sys_user 
        where
            user_id=?

    总结:

        O 对象            两方都使用集合. 
        R 关系型数据库    使用中间表.至少两列.作为外键引用两张表的主键.
        M 映射文件        多: <set name="" table="中间表名" >
                                <key column="别人引用我" />
                                <man-to-many class="" column="我引用别人的" />
                            </set>
                            
        操作:操作管理级别属性. 
            cascade: 级联操作    
                减少我们书写的操作代码.
                none(默认值)    不级联
                save-update:    级联保存
                delete:            级联删除
                all:            级联保存+级联删除
            结论: 可以使用save-update.不推荐使用delete. 也可以不用cascade.
            inverse: 反转关系维护
                属于性能优化.必须选择一方放弃维护主键关系.哪方放弃要看业务方向.

    补充:多对多的时候经常用到查询,比如上面查询用户ID为1的用户具有的角色

      用HQL判断两个实体间是否存在一对多关系,用的  in elements, 注意in elements 只能用于where 从句中

    语法如下:

        @Test
        public void fun5() {
            // 1.获取session
            Session session = HibernateUtil.openSession();
    
            String hql = "from Role r where ? in elements(r.users)";
            Query query = session.createQuery(hql);
    
            User user = new User();
            user.setUser_id(1L);
            query.setParameter(0, user);
    
            List<Role> roles = query.list();
            System.out.println(roles);
        }

    查看SQL语句如下:

    Hibernate:
    select
    role0_.role_id as role_id1_0_,
    role0_.role_name as role_nam2_0_,
    role0_.role_state as role_sta3_0_
    from
    sys_role role0_
    where
    ? in (
    select
    users1_.user_id
    from
    sys_user_role users1_
    where
    role0_.role_id=users1_.role_id
    )
    Hibernate:
    select
    users0_.role_id as role_id2_2_0_,
    users0_.user_id as user_id1_2_0_,
    user1_.user_id as user_id1_1_1_,
    user1_.User_name as User_nam2_1_1_,
    user1_.user_state as user_sta3_1_1_
    from
    sys_user_role users0_
    inner join
    sys_user user1_
    on users0_.user_id=user1_.user_id
    where
    users0_.role_id=?
    Hibernate:
    select
    users0_.role_id as role_id2_2_0_,
    users0_.user_id as user_id1_2_0_,
    user1_.user_id as user_id1_1_1_,
    user1_.User_name as User_nam2_1_1_,
    user1_.user_state as user_sta3_1_1_
    from
    sys_user_role users0_
    inner join
    sys_user user1_
    on users0_.user_id=user1_.user_id
    where
    users0_.role_id=?

  • 相关阅读:
    windows任务计划
    PHP创建多级文件夹
    js正则表达式(不断总结中....)
    js随机改变背景颜色
    提高PHP代码质量36计
    PHP中使用Filter进行数据安全过滤
    CSS颜色代码大全
    正则表达式的修饰符
    创建索引视图
    读取xml中的所有文件名
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9381195.html
Copyright © 2011-2022 走看看