三、Hibernate_多表关系&级联操作&外键维护

一、 一对多的ORM关系映射

ORM : Object Relational Mapping 。 对象 关系 映射。

  1. 首先完成Relational数据库表的一对多的关系
  2. 完成Object实体对象的一对多关系
  3. 完成Mapping映射文件中一对多关系的映射配置

一对多的实例:客户-联系人

一个客户(公司)---对应---多个联系人

步骤:

  1. 创建两个数据库表customer,linkman,在多的一方添加外键建立关系
  2. 创建两个实体类Customer和Linkman,在实体类中分别建立与对方的关系
  3. 创建两个实体类对应的配置文件,分别配置完成一对多的关系映射

1.导入jar包(省略)

导入Hibernate所需要的一些jar包。

2. 创建数据库表customer与linkman,并建立联系。R

    创建customer表与linkman表,在多的一方linkman的表中添加外键,指向一的一方的主键
    
    create database hibernate_day03;
    
    use hibernate_day03;
    
    客户表 :
    CREATE TABLE `cst_customer` (
      `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
      `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
      `cust_user_id` bigint(32) DEFAULT NULL COMMENT '负责人id',
      `cust_create_id` bigint(32) DEFAULT NULL COMMENT '创建人id',
      `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
      `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
      `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
      `cust_linkman` varchar(64) DEFAULT NULL COMMENT '联系人',
      `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
      `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
      PRIMARY KEY (`cust_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


    联系人数据库表 :
    CREATE TABLE `cst_linkman` (
      `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
      `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
      `lkm_cust_id` bigint(32) NOT NULL COMMENT '客户id',
      `lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别',
      `lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
      `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',
      `lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
      `lkm_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq',
      `lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',
      `lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',
      PRIMARY KEY (`lkm_id`),KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
      CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    )

3. 创建Customer与Linkman实体类,并建立联系。O

分别在两个实体类中添加与另一个实体类的联系。

Customer的实体类:

三、Hibernate_多表关系&级联操作&外键维护_第1张图片
img17.png

Linkman的实体类:

三、Hibernate_多表关系&级联操作&外键维护_第2张图片
img18.png
4. 在对应的映射文件中添加一对多的映射关系

Customer.hbm.xml映射文件:


    
    
    
        
        
    

Linkman.hbm.xml映射文件:


    
    
    
5.在核心配置文件中加载映射文件

    
    
    
    
     
    
        
            
            com.mysql.jdbc.Driver
            jdbc:mysql://localhost:3306/hibernate_day03
            root
            root
            
            
            thread
            
            
            
            org.hibernate.dialect.MySQLDialect
            
            
            true
            
            
            true
            
            
            none
            
            
            4
            
            
            org.hibernate.c3p0.internal.C3P0ConnectionProvider
            
            5
            
            20
            
            120
            
            120
            
            120
            
            2
            
            false
            
            
            
            
        
    

6.Hibernate:1对多关系测试

    /**
     * 测试数据库表的1对多关系:
     */
    
    @Test
    //保存一个客户与两个联系人
    public void test() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //------------------------------------------
        
        //1> 创建一个客户
        Customer customer = new Customer();
        customer.setCust_name("阿里巴巴");
        
        //2> 创建两个联系人
        Linkman linkeman = new Linkman();
        linkeman.setLkm_name("小马");
        
        Linkman linkeman2 = new Linkman();
        linkeman2.setLkm_name("小云");
        
        //3> 表达一对多,客户下有多个联系人
        customer.getLinkemans().add(linkeman);
        customer.getLinkemans().add(linkeman2);
        
        //4> 表达多对一,联系人属于哪个客户
        linkeman.setCustomer(customer);
        linkeman2.setCustomer(customer);
        
        //5> 保存.将瞬时态对象转换成持久态对象
        session.save(customer);
        session.save(linkeman);
        session.save(linkeman2);
        
        //------------------------------------------
        //提交事务
        transaction.commit();
    }
    
    
    @Test
    //为客户1添加一个联系人
    public void test2() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //------------------------------------------
        
        //1> 获取客户1
        Customer customer = session.get(Customer.class, 1L);
        
        //2> 创建待添加的联系人
        Linkman linkeman = new Linkman();
        linkeman.setLkm_name("刘总");
        
        //3> 建立关系:表达一对多,客户下有多个联系人
        customer.getLinkemans().add(linkeman);
        
        //4> 建立关系:表达多对一,联系人属于哪个客户
        linkeman.setCustomer(customer);
        
        //5> 保存.将瞬时态对象转换成持久态对象
        //session.save(customer);(customer是持久态对象无需手动保存,会自动更新数据库)
        session.save(linkeman);
        
        //------------------------------------------
        //提交事务
        transaction.commit();
    }
    
    
    @Test
    //为客户1删除一个联系人刘总
    public void test3() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //------------------------------------------
        
        //1> 获取客户1
        Customer customer = session.get(Customer.class, 1L);
        
        //2> 获取待删除的联系人
        Linkman linkeman = session.get(Linkman.class, 3L);
        
        //3> 建立关系:从客户的联系人集合中删除该联系人
        customer.getLinkemans().remove(linkeman);
        
        //4> 建立关系:从联系人的客户引用中删除该客户
        linkeman.setCustomer(null);
        
        //5> 保存.将瞬时态对象转换成持久态对象(customer与linkman都是持久态对象,无需保存会自动更新)
        //session.save(customer);
        //session.save(linkeman);
        
        //------------------------------------------
        //提交事务
        transaction.commit();
    }


上面在操作瞬时态对象时,每个瞬时态对象都要手动进行save保存,为了节省代码,Hibernate提供了级联操作。只要设置了级联的这一方添加了级联配置,与它产生关系的另一方就无需在进行save或者update等操作了。

级联测试:


    在客户的一端设置级联保存,那么只要客户是持久化状态,就无需对与其产生关系的联系人进行save或者update操作了.

     

    
        
        
      


    
    @Test
    //保存一个客户与两个联系人(级联保存)
    //为了简化代码操作,在做session.save时,save客户就可以同时将客户中的ecustomer对象保存.
    //但是,如果直接省略,会报错:瞬时态与执行态关联的错误.因此在需要做级联保存的映射文件中配置,将cascad属性设为save-update即可
    public void test1() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //------------------------------------------
        
        //1> 创建一个客户
        Customer customer = new Customer();
        customer.setCust_name("阿里巴巴");
        
        //2> 创建两个联系人
        Linkman linkeman = new Linkman();
        linkeman.setLkm_name("小马");
        
        Linkman linkeman2 = new Linkman();
        linkeman2.setLkm_name("小云");
        
        //3> 建立关系:将联系人添加到客户的集合中
        customer.getLinkemans().add(linkeman);
        customer.getLinkemans().add(linkeman2);
        
        //4> 建立关系:将客户添加到联系人中
        linkeman.setCustomer(customer);
        linkeman2.setCustomer(customer);
        
        //5> 保存.将瞬时态对象转换成持久态对象
        session.save(customer);
        //在customer的映射文件中配置级联保存,在保存customer的时候会自动保存与它产生关联的联系人
        // session.save(linkeman);
        // session.save(linkeman2);
        
        //------------------------------------------
        //提交事务
        transaction.commit();
    }
    
    
    @Test
    //为添加一个联系人(级联保存)
    //为了简化代码操作,在做session.save时,save客户就可以同时将客户中的ecustomer对象保存.
    //但是,如果直接省略,会报错:瞬时态与执行态关联的错误.因此在需要做级联保存的映射文件中配置,将cascad属性设为save-update即可
    public void test2() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //------------------------------------------
        
        //1> 获取客户1
        Customer customer = session.get(Customer.class, 1L);
        //2> 创建一个联系人
        Linkman linkeman = new Linkman();
        linkeman.setLkm_name("小白");
        
        //3> 建立关系:将联系人添加到客户的集合中
        customer.getLinkemans().add(linkeman);
        
        //4> 建立关系:将客户添加到联系人中
        linkeman.setCustomer(customer);
        
        //5> 保存.customer通过get方法取出就是持久态了,无需手动保存
        //因为配置了级联保存,保存customer的时候Hibernate会自动将与这个customer产生关系的linkman设为持久态保存
        //session.save(customer);
        
        //------------------------------------------
        //提交事务
        transaction.commit();
    }
    
    
    @Test
    //为客户1删除联系人id为1的小马,增加一个联系人为小宋
    public void test4() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //-------------------------------
        //实现业务逻辑 : 为客户1删除联系人id为1的小马,增加一个联系人为小宋
        //1> 获取客户1
        Customer customer = session.get(Customer.class, 1L);
        
        //2> 获取要删除的联系人小马
        Linkman linkman = session.get(Linkman.class, 1L);
        
        //3> 创建一个联系人小宋
        Linkman linkman2 = new Linkman();
        linkman2.setLkm_name("小宋");
        
        //4> 建立关系: 在客户1方建立对联系人的关系
        //从联系人集合中删除要删除的联系人
        customer.getLinkemans().remove(linkman);
        //添加要添加的联系人到联系人集合
        customer.getLinkemans().add(linkman2);
        
        //5> 建立关系: 在联系人放建立对客户1的关系
        //解除客户在联系人的引用
        linkman.setCustomer(null);
        //在添加的联系人的客户引用中添加客户1
        linkman2.setCustomer(customer);
        
        //6> 保存
        //customer是持久态,删除的联系人也是持久态,待添加的联系人不是持久态,但是由于customer设置了级联保存因此也无需save保存
        //-------------------------------
        //提交事务
        transaction.commit();
        //关闭资源,getCurrentSession方法获得与线程绑定的Session对象无需手动关闭
    }
    
    
    @Test
    //级联删除 : 在实际开发中基本不用,这里测试使用
    //目的:在删除联系人的时候将它的客户也删除掉
    public void test5() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //-------------------------------
        //实现业务逻辑 : 删除联系人1的时候将它的客户也删除掉
        //1> 获取要删除的联系人
        Linkman linkman = session.get(Linkman.class, 1L);
        
        //2> 删除联系人
        session.delete(linkman);
        
        //3> 保存
        //linkman是持久态,无需手动保存,同时它设置了级联删除,因此删除联系人的同时,会将它对应的客户1也删除掉
        //如果这个时候在客户的一方也设置级联删除,会导致删除一个客户或者删除一个联系人,会将与它有关联的所有数据都删除掉
        //-------------------------------
        //提交事务
        transaction.commit();
        //关闭资源,getCurrentSession方法获得与线程绑定的Session对象无需手动关闭
    }

上面通过级联的配置,节省了一些多余代码的操作,但是我们通过查看Hibernate打印的sql语句发现(例如执行test1的代码),Hibernate会对外键lkm_cst_id进行多余的两次操作.Linkman自身在insert添加新联系人时已经维护了外键lkm_cst_id,那么下面update进行的维护很显然就是客户customer在进行维护,这是很冗余的操作。因此我们需要通过配置进行优化,Hibernate提供了inverse的属性来设置。

三、Hibernate_多表关系&级联操作&外键维护_第3张图片
img21.png

      

    
            
            
    


    //操作进阶--关系维护属性
    public class Demo3 {
        @Test
        //保存客户 以及客户 下的联系人
        public void fun1(){
            //1 获得session
            Session session = HibernateUtils.openSession();
            //2 开启事务
            Transaction tx = session.beginTransaction();
            //-------------------------------------------------
            //3操作
            Customer c = new Customer();
            c.setCust_name("阿里巴巴");
            
            LinkMan lm1 = new LinkMan();
            lm1.setLkm_name("小马");
            
            LinkMan lm2 = new LinkMan();
            lm2.setLkm_name("小云");
            
            //表达一对多,客户下有多个联系人. 
            // 如果客户放弃维护与联系人的关系. 维护关系的代码可以省略
            //c.getLinkMens().add(lm1);
            //c.getLinkMens().add(lm2);
            
            //表达多对多,联系人属于哪个客户
            lm1.setCustomer(c);
            lm2.setCustomer(c);
            
            //如果Linkman的配置文件中配置了级联保存,则这条保存客户的语句可以省略
            //session.save(c);
            session.save(lm1);
            session.save(lm2);
            
            //-------------------------------------------------
            //4提交事务
            tx.commit();
            //5关闭资源
            session.close();
        }

上面的配置表示:customer放弃外键维护lkm_cst_id.那么同样再执行test1的代码时,下面update的冗余的sql语句就消失了,达到了优化的目的.

三、Hibernate_多表关系&级联操作&外键维护_第4张图片
img22.png

二、 多对多的ORM关系映射

ORM : Object Relational Mapping 。 对象 关系 映射。

  1. 首先完成Relational数据库表的多对多的关系表达(外键)
  2. 完成Object实体对象的多对多关系表达(分别创建Set集合存储对方的对象)
  3. 完成Mapping映射文件中一对多关系的映射配置(配置)

多对多的实例

用户与角色(岗位) User & Role

    一个用户可以在公司中担任多个岗位
    一个岗位上也有多个员工用户在工作
1.jar包上面一对多的例子已经导入
2.创建多对多的两个数据库表,进行关系表达 Relational
    
    多对多的数据库多表关系表达,需要创建一个第三方表,这个第三方表至少有两个字段,分别指向两张表的主键.

    
    -- 用户表

    CREATE TABLE `sys_user` (
      `user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id',
      `user_code` varchar(32) NOT NULL COMMENT '用户账号',
      `user_name` varchar(64) NOT NULL COMMENT '用户名称',
      `user_password` varchar(32) NOT NULL COMMENT '用户密码',
      `user_state` char(1) NOT NULL COMMENT '1:正常,0:暂停',
      PRIMARY KEY (`user_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

    
    -- 用户角色表. 
    
    CREATE TABLE `sys_role` (
      `role_id` bigint(32) NOT NULL AUTO_INCREMENT,
      `role_name` varchar(32) NOT NULL COMMENT '角色名称',
      `role_memo` varchar(128) DEFAULT NULL COMMENT '备注',
      PRIMARY KEY (`role_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;


    -- 第三方表,负责维护user与role表的关系
    
    CREATE TABLE `sys_user_role` (
      `role_id` bigint(32) NOT NULL COMMENT '角色id',
      `user_id` bigint(32) NOT NULL COMMENT '用户id',
      PRIMARY KEY (`role_id`,`user_id`),
      KEY `FK_user_role_user_id` (`user_id`),
      CONSTRAINT `FK_user_role_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
      CONSTRAINT `FK_user_role_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.创建多对多的两个实体类,进行关系表达 Object

    /**
     * 持久化类:用户实体类
     */
    public class User {
    
        // 普通属性
        private Long user_id;//外键
        private String user_code;
        private String user_name;
        private String user_password;
        private Character user_state;
    
        // 建立多对多关系:Set集合存储当前User对象持有的Role角色信息
        private Set roles = new HashSet<>();



    /**
     * 持久化类:用户角色的实体类
     */
    public class Role {
    
        // 普通属性
        private Long role_id;//外键
        private String role_name;
        private String role_memo;
    
        // 建立实体类多对多关系:Set集合存储属于该Role角色的所有User对象
        private Set users = new HashSet<>();
4.配置两个映射文件,进行关系表达 Mapping

    User.hbm.xml映射文件配置多对多关系:

     
    
    
        
        
    

    ------------------------------------------------------------

    Role.hbm.xml映射文件配置多对多关系:

     
    
    
        
        
    

4.在hibernate.cfg.xml中加载映射文件:

    
    
4.Hibernate多对多关系测试

    /**
     * Hibernate多对多关系测试
     */
    
    @Test
    //多对多关系:创建两个用户,创建三个角色由两个用户分配保存
    public void test1() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        
        //----------------------------
        //实现业务逻辑
        //1> 创建两个用户
        User user = new User();
        User user2 = new User();
        user.setUser_name("杨幂");
        user2.setUser_name("唐嫣");
        
        //2> 创建三个角色(岗位)
        Role role = new Role();
        Role role2 = new Role();
        Role role3 = new Role();
        role.setRole_name("明星");
        role2.setRole_name("女儿");
        role.setRole_name("妻子");
        
        //3> 用户表达关系:分别在用户中添加角色
        //杨幂持有明星,女儿,妻子三个角色
        user.getRoles().add(role);
        user.getRoles().add(role2);
        user.getRoles().add(role3);
        //唐嫣持有明星和女儿两个角色
        user2.getRoles().add(role);
        user2.getRoles().add(role2);
        
        //4> 角色表达关系:分别在角色中添加用户
        role.getUsers().add(user);
        role2.getUsers().add(user);
        role3.getUsers().add(user);
        
        role.getUsers().add(user2);
        role2.getUsers().add(user2);
        
        //5> 保存
        session.save(user);
        session.save(user2);
        session.save(role);
        session.save(role2);
        session.save(role3);
        
        //----------------------------
        //提交事务
        transaction.commit();
    }

    ==================================================

    我们按照非常正规的方式,分别建立了user和role对象然后逐个保存,但是就是这么看起来正确的操作却报错了。

    org.hibernate.exception.ConstraintViolationException: could not execute statement

    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
        Duplicate entry '1-1' for key 'PRIMARY'

    根据日志错误信息,我们知道产生了重复的主键:1-1.

    这是因为我们的第三方表只有两个字段,就是两张表的外键,这张表的主键就是两个外键组成的联合主键。
    那为什么会产生重复的主键1-1呢?

    我们在上面inverse外键维护关系的属性时讲了,inverse默认值是false,默认维护外键.
    我们在建立关系的时候,user一方建立了关系-getRoles.add(user).role一方也建立了关系-getUsers.add(role);
    这样它们在维护外键时会导致user维护了外键往第三方表插入了1 1. role在维护外键时也会往第三方表插入1 1.导致联合主键重复了。

    ======================================================

    要解决这一问题,有两种方式:

    方式1: 只让一方建立关系
        即: 注释掉一方的建立关系,例如注释掉role方建立与user的关系表达
        将 role.getUsers.add(role)的语句全都注释掉就可以了。
        但是这种方式,我们看起来不是很舒服,因为感觉不够符合逻辑。
        建立关系应该是两方都建立。因此就可以使用方式2.

    --------------------------------------------------------

    方式2: 让被动的一方放弃外键维护
    在这里因为user是主动选择的role角色,因此让role放弃外键维护

    
            

    
        
        
    
    

设置级联保存

在上面的测试中,在保存瞬时态对象到一级缓存中时,需要将每一个瞬时态对象都一一save,为了节省代码,我们使用级联保存来解决。


    // 5> 保存
    //正常操作需要save保存每一个瞬时态对象,为了节省这些代码,我们使用级联保存cascade
    //分别在User.hbm.xml与Role.hbm.xml映射文件中设置级联配置

        
    Role.hbm.xml :  
    
        
        
    

    User.hbm.xml : 
    
            
            
    

    ==================================================================

    //这样设置之后,只需要保存其中一个对象都能级联将其它瞬时对象全都保存.(要保证所有的对象都能被关联到)
    //例如,保存user,会级联保存与它建立关系的role,role2,role3.而role,role2,与user和uer2产生了关联,因此user2也成功保存
    //又如,保存role3,会级联保存与role3建立了关系的user2,user2会级联保存role和role2,role和role2又能级联保存user
    session.save(user);
    // session.save(user2);
    // session.save(role);
    // session.save(role2);
    // session.save(role3);

为用户添加角色:


    //为唐嫣增加一个角色 : 女神
    @Test
    public void test2() {
        //获得Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //----------------------------------
        //实现业务逻辑
        //1> 获取user对象唐嫣
        User user = session.get(User.class, 2L);
        
        //2> 创建一个新的角色:女神
        Role role = new Role();
        role.setRole_name("女神");
        
        //3> user表达关系: 将新建的角色添加到user对象的角色集合中
        user.getRoles().add(role);
        
        //4> role表达关系 : 将user对象添加到role对象的用户集合中
        role.getUsers().add(user);
        
        //5> 保存转化为持久态
        // user对象已经是持久态了,无需手动保存,又因为添加了级联保存,所以会级联保存role对象
        
        //----------------------------------
        //提交事务(事务提交时,数据更新到数据库,清空一级缓存区)
        transaction.commit();
    }

为唐嫣解除明星角色


    @Test
    //为唐嫣解除明星角色
    public void test3() {
        //获取Session对象
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //---------------------------------------------
        //处理业务逻辑
        //1> 获取User对象唐嫣:id为2
        User user = session.get(User.class, 2L);
        
        //2> 获取Role对象明星:id为2
        Role role = session.get(Role.class, 2L);
        
        //3> User表达关系:从role集合中移除明星角色
        user.getRoles().remove(role);
        
        //4> Role表达关系:从user集合中移除用户唐嫣
        role.getUsers().remove(user);
        
        //5> 保存,将瞬时态对象转换为持久态
        //user与role对象已经持久态了
        
        //---------------------------------------------
        //提交事务
        transaction.commit();
    }

cascade与inverse使用总结:

  • cascade : 实质上是为了节省代码操作

    cascade级联操作:
        save-update: 级联保存更新
        delete:级联删除
        all:级联保存更新+级联删除
        结论: cascade简化代码书写.该属性使不使用无所谓. 建议要用只用save-update.
        使用delete操作太过危险.尤其在多对多中.不建议使用.
  • inverse : 减少多余的sql语句,优化Hibernate的性能
    
    双向建立关系时,双方都进行外键维护产生了多余的sql语句,使用inverse属性使一方放弃外键维护。

    使用inverse属性
        true: 放弃维护外键关系
        false(默认值):维护关系
    
    结论: 
        在一对多关系中,通常选择一的一方放弃外键维护。

        多对多关系中.一定要选择一方放弃维护关系.
         一般谁来放弃要看业务方向(被动一方放弃维护). 例如录入员工时,需要为员工指定所属角色.
         那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护   

你可能感兴趣的:(三、Hibernate_多表关系&级联操作&外键维护)