zoukankan      html  css  js  c++  java
  • Hibernate中的多对多关系详解(3)​

    前面两节我们讲到了一对一的关系,一对多,多对一的关系,相对来说,是比较简单的,但有时,我们也会遇到多对多的关系,比如说:角色与权限的关系,就是典型的多对多的关系,因此,我有必要对这种关系详解,以便大家一起学习。下面来看例子:

    首先我们必须建立二者的vo:

    public class Role implements Serializable {//这是role对象
        private Integer rid;
        private String rdesc;
        private String rname;
        
        private Set<Function> funs = new HashSet<Function>();
              ....get,set方法已省略
        //这里重新写hashcode()与equals()是因为在set集合中不允许有重复的对象,也防止在添加时会重复添加相同的数据
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((rdesc == null) ? 0 : rdesc.hashCode());
            result = prime * result + ((rname == null) ? 0 : rname.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Role other = (Role) obj;
            if (rdesc == null) {
                if (other.rdesc != null)
                    return false;
            } else if (!rdesc.equals(other.rdesc))
                return false;
            if (rname == null) {
                if (other.rname != null)
                    return false;
            } else if (!rname.equals(other.rname))
                return false;
            return true;
        }
    }
    public class Function implements Serializable {//function的vo,也就是权限
        
        private Integer fid;
        private String fname;
        private String fdesc;
        
        private Set<Role> roles = new HashSet<Role>();
    
       //get,set方法已省略,对hashcode等方法如上同
    }

    下面我们配置各自的mapping文件:

    <?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">
    <hibernate-mapping package="com.ysq.vo" >
     <class name="Role" table="y_role">
       <id name="rid">
         <generator class="sequence">
            <param name="sequence">dept_seq</param>
         </generator>
       </id>
    
       <property name="rname" length="20"></property>
       <property name="rdesc" length="20"></property>
       
       <!-- *****cascade="save-update":如果设置成all,删除的时候,会把另外中的数据删除了
        --><!-- role对中间表可以设为一对多情况         table是多对多中的中间表名 -->
       <set name="funs" table="y_role_fun" fetch="join" cascade="save-update" lazy="false">
          <key column="rid"></key><!-- 当前这个类所对应的表的中间表的外键字段 -->
          <many-to-many class="Function" column="fid"></many-to-many>
       </set>
     </class>
    </hibernate-mapping>
    <?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">
    <hibernate-mapping package="com.ysq.vo" >
     <class name="Function" table="y_fun">
        <id name="fid">
          <generator class="sequence">
             <param name="sequence">dept_seq</param>
          </generator>
        </id>
        <property name="fname" length="20"/>
        <property name="fdesc" length="20"/>
        <!-- 权限表对中间表相当于一对多的情况     使用控制反转 使对中间表的权限交给role表来控制-->
       <set name="roles" table="y_role_fun" inverse="true">
         <key column="fid"></key><!-- y_fun在中间表所对应的外键 -->
         <many-to-many class="Role" column="rid"></many-to-many>
       </set>
     </class>
    </hibernate-mapping>

    编写测试类:

    public class many_to_many_Test {
    
        /**
         * 如果不需要控制反转的话,不能设置双向关联,不然会在中间表中添加重复字段
         */
        @Test
        public void addRole(){
            Role role = new Role();
            Function fun = new Function();
            Function fun1 = new Function();
            Function fun2 = new Function();
            
            role.setRname("经理");
            role.setRdesc("公司上下");
            
            fun.setFname("用户添加");
            fun.setFdesc("用户添加");
            fun1.setFname("用户删除");
            fun1.setFdesc("用户删除");
            fun2.setFname("用户修改");
            fun2.setFdesc("用户修改");
            
            
            Session session = SessionFactoryUtils.getSession();
            Transaction tr = session.beginTransaction();
            tr.begin();
            
            //设置单向关联
             /*fun.getRoles().add(role);
            fun1.getRoles().add(role);
            fun2.getRoles().add(role); *///如果设置了控制反转,可以不设置双向关联
            
            role.getFuns().add(fun);
            role.getFuns().add(fun1);
            role.getFuns().add(fun2);
            
            session.save(role);
            
            tr.commit();
            session.close();
        }
        
    
        /**
         * 删除某一角色的中的某一种权限:先查询该角色所拥有的权限,然后for遍历删除对应的权限
         */
        @Test
        public void deleteRole(){
            Session session = SessionFactoryUtils.getSession();
            Transaction tx = session.beginTransaction();
            
            try {
                tx.begin();
                
                Role role = (Role)session.get(Role.class, 9);
                Set<Function> funs = role.getFuns();
                 /*for (Iterator iterator = funs.iterator(); iterator.hasNext();) {
                    Function function = (Function) iterator.next();
                    if(function.getFid() == 10){
                       iterator.remove();
                       break;
                    }
                } */
                  for (Function function : funs) {
                     //删除set中对应的权限
                     if(function.getFid() == 11){
                         funs.remove(function);//移除set中的此权限
                         break;//注意:这里必须要break,这与set集合中删除时游标有关
                    }     
                }         
                //在重新更新此角色的权限列表
                role.setFuns(funs);
                session.update(role);
                 
                tx.commit();
            } catch (Exception e) {
                // TODO: handle exception
                tx.rollback();
                e.printStackTrace();
            }finally{
                session.close();
            }
        }
        /**
         * join fetch  【有set集合,不能用join fetch】
         */
        @Test
        public void findRole(){
            Session session = SessionFactoryUtils.getSession();
            List<Role> roles =  session.createQuery("from Role").list();
            session.close();
            
            for (Role role : roles) {
                System.out.println(role.getRname());
                if(role.getFuns().size() > 0){
                    for (Function fun: role.getFuns()) {
                        System.out.println(fun.getFname());
                    }
                }
            }
        }
    }
    生活赋予我们一种巨大的和无限高贵的礼品,这就是青春:充满着力量,充满着期待志愿,充满着求知和斗争的志向,充满着希望信心和青春。
  • 相关阅读:
    android中的Cursor类
    设计模式之UML类图的常见关系(一)
    关于form 上传文件时的小问题
    Javascript中最常用的61段经典代码
    自我提升mysql
    为mysql在表的某一位置增加一列
    由<a>标签的onclick影出来的问题
    第一博客
    异常的出理
    2016.7.17内部类
  • 原文地址:https://www.cnblogs.com/ysq0908/p/4761903.html
Copyright © 2011-2022 走看看