JavaWeb - Hibernate框架使用(三)

表与表的关系

关键是维护关联属性

一对多|多对一

一对多(多对一):

  • 数据表中:

客户表

cid cname
1 百度
2 网易

​ 联系人表

lid lname cid
1 张总 1
2 刘总 1
3 王总 2
  • 实体中:

    客户(Cudtomer)实体:

    private Long cid;
    private String cname;
    //使用集合表达‘一’的一方拥有多个‘多’的一方
    private Set linkMen;
    

    联系人(LinkMan)实体:

    private Long lid;
    private String lname;
    //使用对象引用‘一’的一方表达‘多’的一方属于哪个‘一’的一方
    private Customer customer;
    
  • orm元数据中:

    Customer.hbm.xml中(‘一’的一方):

      
          
              
          
          
          
          
          
          
          
          
      
          
          
           
            
          
              
              
          
      
    

    LinkMan.hbm.xml中(‘多’的一方):

      
          
              
          
          
          
          
          
          
          
          
          
          
          
          
            
            
          
          
      
    
  • 操作关联属性:

    • 基本操作
      //一对多|多对一关系操作
      public class Demo {
      @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);
          
          
          session.save(c);
      /       session.save(lm1);
      /       session.save(lm2);
          
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
    
      @Test
      //为客户增加联系人
      public void fun2(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 获得要操作的客户对象
          Customer c = session.get(Customer.class,1l);
          //2> 创建联系人
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("郝强勇");
          //3> 将联系人添加到客户,将客户设置到联系人中
          c.getLinkMens().add(lm1);
          lm1.setCustomer(c);
          //4> 执行保存
          session.save(lm1);
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
    
      @Test
      //为客户删除联系人
      public void fun3(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 获得要操作的客户对象
          Customer c = session.get(Customer.class,1l);
          //2> 获得要移除的联系人
          LinkMan lm = session.get(LinkMan.class, 3l);
          //3> 将联系人从客户集合中移除
          c.getLinkMens().remove(lm);
          lm.setCustomer(null);
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
    }
    
    • 进阶 - 级联

      cascade属性值:save-update,不建议delete

      级联的效果只是简化操作,可以少写几句代码。

    
    //测试级联操作
    public class Demo2 {
      @Test
      //保存客户 以及客户 下的联系人
      //cascade:save-update
      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);
          
          
          session.save(c);
    //        session.save(lm1);
    //        session.save(lm2);
          
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
      
      @Test
      //测试删除客户时,级联删除客户下的联系人
      //cascade:delete
      public void fun2(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 获得要操作的客户对象
          Customer c = session.get(Customer.class,1l);
          //2>调用delete删除客户
          session.delete(c);
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
      
      @Test
      //保存联系人以及联系人对应的客户
      //cascade:save-update
      public void fun3(){
          //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("刘总");
          
          //表达一对多,客户下有多个联系人
          c.getLinkMens().add(lm1);
          
          //表达对对对,联系人属于哪个客户
          lm1.setCustomer(c);
          
          
          session.save(lm1);
          
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
          
    }
    
    • 进阶 - 关系维护

      优化性能效率:在保存时.两方都会维护外键关系.关系维护两次,冗余了. 多余的维护关系语句,显然是客户这一端在维护关系。

      inverse属性值true时表示当前配置的这一方放弃维护(字面意思反转嘛),默认为false。

    //操作进阶--关系维护属性
    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);
          
          
          session.save(c);
          session.save(lm1);
          session.save(lm2);
          
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
      
      @Test
      //删除客户
      public void fun2(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer customer = session.get(Customer.class, 1l);
          
          session.delete(customer);
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
          
    }
    

多对多

数据表中

员工表

uid uname
1 张三
2 李四
3 王五

角色表

rid rname
1 清洁工
2 总裁
3 前台

员工角色表(采用中间表设计原则)

uid rid
1 1
1 3
2 2
3 1

实体中:(使用集合来表达互相拥有多个对方)

员工(User)

private Long uid;
private String uname;
private Set roles;

角色(Role)

private Long rid;
private String rname;
private Set users;

orm元数据中

User.hbm.xml

    
        
            
        
        
        
        
        
    
        
        
         
        
            
            
        
    
    

Role.hbm.xml

    
        
            
        
        
        

            
        
            
            
        
    
  • 操作关联属性

    基本操作

    //多对多关系操作
    public class Demo {
      @Test
      //保存员工以及角色
      public void fun1(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 创建两个 User
          User u1 = new User();
          u1.setUser_name("郝强勇");
          
          User u2 = new User();
          u2.setUser_name("金家德");
          
          //2> 创建两个 Role
          Role r1 = new Role();
          r1.setRole_name("保洁");
          
          Role r2 = new Role();
          r2.setRole_name("保安");
          //3> 用户表达关系
          u1.getRoles().add(r1);
          u1.getRoles().add(r2);
          
          u2.getRoles().add(r1);
          u2.getRoles().add(r2);
          
          //4> 角色表达关系
          r1.getUsers().add(u1);
          r1.getUsers().add(u2);
          
          r2.getUsers().add(u1);
          r2.getUsers().add(u2);
          
          //5> 调用Save方法一次保存
          session.save(u1);
          session.save(u2);
          session.save(r1);
          session.save(r2);
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
      
      
      @Test
      //为郝强勇新增一个角色
      public void fun3(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 获得郝强勇用户
          User user = session.get(User.class, 1l);
          //2> 创建公关角色
          Role r = new Role();
          r.setRole_name("男公关");
          //3> 将角色添加到用户中
          user.getRoles().add(r);
          //4> 将角色转换为持久化
          //session.save(r);
          //若在User.hbm.xml中配置了cascade属性为save-update,则可以级联保存,就不必写上面这句代码
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
      
      @Test
      //为郝强勇解除一个角色
      public void fun4(){
          //1 获得session
          Session session = HibernateUtils.openSession();
          //2 开启事务
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 获得郝强勇用户
          User user = session.get(User.class, 1l);
          //2> 获得要操作的角色对象(保洁,保安)
          Role r1 = session.get(Role.class, 1l);
          Role r2 = session.get(Role.class, 2l);
          //3> 将角色从用户的角色集合中移除
          user.getRoles().remove(r1);
          user.getRoles().remove(r2);
          
          //-------------------------------------------------
          //4提交事务
          tx.commit();
          //5关闭资源
          session.close();
      }
    }
    

    进阶 - inverse属性:

    使用inverse属性
              true: 放弃维护外键关系
              false(默认值):维护关系
              
          结论: 将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.
               一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.
               那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护
    

    进阶 - 级联属性

    cascade级联操作:
                      save-update: 级联保存更新
                      delete:级联删除
                      all:级联保存更新+级联删除
              结论: cascade简化代码书写.该属性使不使用无所谓. 建议要用只用save-update.
                   如果使用delete操作太过危险.尤其在多对多中.不建议使用.
    

你可能感兴趣的:(JavaWeb - Hibernate框架使用(三))