美文网首页
JavaWeb - Hibernate框架使用(三)

JavaWeb - Hibernate框架使用(三)

作者: 小闫94 | 来源:发表于2018-03-28 14:22 被阅读0次

表与表的关系

关键是维护关联属性

一对多|多对一

一对多(多对一):

  • 数据表中:

客户表

cid cname
1 百度
2 网易

​ 联系人表

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

    客户(Cudtomer)实体:

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

    联系人(LinkMan)实体:

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

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

      <class name="Customer" table="cst_customer" >
          <id name="cust_id"  >
              <generator class="native"></generator>
          </id>
          <property name="cust_name" column="cust_name" ></property>
          <property name="cust_source" column="cust_source" ></property>
          <property name="cust_industry" column="cust_industry" ></property>
          <property name="cust_level" column="cust_level" ></property>
          <property name="cust_linkman" column="cust_linkman" ></property>
          <property name="cust_phone" column="cust_phone" ></property>
          <property name="cust_mobile" column="cust_mobile" ></property>
      
          <!-- 集合,一对多关系,在配置文件中配置 -->
          <!-- 
              name属性:集合属性名
              column属性: 外键列名
              class属性: 与我关联的对象完整类名
           -->
           <!-- 
              级联操作:   cascade
                  save-update: 级联保存更新
                  delete:级联删除
                  all:save-update+delete
              级联操作: 简化操作.目的就是为了少些两行代码.
            -->
            <!-- inverse属性: 配置关系是否维护. 
                  true: customer不维护关系
                  false(默认值): customer维护关系
    
              inverse属性: 性能优化.提高关系维护的性能.
              原则: 无论怎么放弃,总有一方必须要维护关系.
              一对多关系中: 一的一方放弃.也只能一的一方放弃.多的一方不能放弃.
            -->
          <set name="linkMens" inverse="true" cascade="delete"  >
              <key column="lkm_cust_id" ></key>
              <one-to-many class="LinkMan" />
          </set>
      </class>
    

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

      <class name="LinkMan" table="cst_linkman" >
          <id name="lkm_id"  >
              <generator class="native"></generator>
          </id>
          <property name="lkm_gender"  ></property>
          <property name="lkm_name"  ></property>
          <property name="lkm_phone"  ></property>
          <property name="lkm_email"  ></property>
          <property name="lkm_qq"  ></property>
          <property name="lkm_mobile"  ></property>
          <property name="lkm_memo"  ></property>
          <property name="lkm_position"  ></property>
          
          <!-- 多对一 -->
          <!-- 
              name属性:引用属性名
              column属性: 外键列名
              class属性: 与我关联的对象完整类名
           -->
            <!-- 
              级联操作:   cascade
                  save-update: 级联保存更新
                  delete:级联删除
                  all:save-update+delete
              级联操作: 简化操作.目的就是为了少些两行代码.
            -->
            <!-- 多的一方: 不能放弃维护关系的.外键字段就在多的一方.  -->
          <many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
          </many-to-one>
      </class>
    
  • 操作关联属性:

    • 基本操作
      //一对多|多对一关系操作
      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<Role> roles;

角色(Role)

private Long rid;
private String rname;
private Set<User> users;

orm元数据中

User.hbm.xml

    <class name="User" table="sys_user" >
        <id name="user_id"  >
            <generator class="native"></generator>
        </id>
        <property name="user_code"  ></property>
        <property name="user_name"  ></property>
        <property name="user_password"  ></property>
        <property name="user_state"  ></property>
    
        <!-- 多对多关系表达 -->
        <!-- 
            name: 集合属性名
            table: 配置中间表名
            key
             |-column:外键,别人引用"我"的外键列名
             class: 我与哪个类是多对多关系
             column:外键.我引用比人的外键列名
         -->
         <!-- cascade级联操作:
                    save-update: 级联保存更新
                    delete:级联删除
                    all:级联保存更新+级联删除
            结论: cascade简化代码书写.该属性使不使用无所谓. 建议要用只用save-update.
                 如果使用delete操作太过危险.尤其在多对多中.不建议使用.
                     -->
        <set name="roles" table="sys_user_role" cascade="save-update" >
            <key column="user_id" ></key>
            <many-to-many class="Role" column="role_id" ></many-to-many>
        </set>
    
    </class>

Role.hbm.xml

    <class name="Role" table="sys_role" >
        <id name="role_id"  >
            <generator class="native"></generator>
        </id>
        <property name="role_name"  ></property>
        <property name="role_memo"  ></property>

    <!-- 使用inverse属性
            true: 放弃维护外键关系
            false(默认值):维护关系
            
        结论: 将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.
             一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.
             那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护
         -->        
        <set name="users" table="sys_user_role" inverse="true" >
            <key column="role_id" ></key>
            <many-to-many class="User" column="user_id" ></many-to-many>
        </set>
    </class>
  • 操作关联属性

    基本操作

    //多对多关系操作
    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框架使用(三)

      本文链接:https://www.haomeiwen.com/subject/dxwycftx.html