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());
                }
            }
        }
    }
}

 

posted @ 2015-08-26 22:41  goodTOgreat  阅读(171)  评论(0编辑  收藏  举报