Hibernate关系映射(七)多对多双向关联@ManyToMany Annotation方式

本篇介绍多对多的双向关联,也是Hibernate关系映射的结尾篇,后续篇章会介绍Hibernate的懒加载机制和级联相关操作。


首先还是来模拟一个实际应用的场景,在之前开发过的RBAC模型中,有这样一个关系,用户组中包含多个用户,每一个用户可以属于多个用户组,那么这就是一个多对多的关系,而我又需要从当前用户组读取到包含哪些用户,又需要从当前用户获取他在哪些组中。那么就需要建立双向关联。
Entity:UserGroup
Attr:id(Integer)
name(String)
users(Set< User >)

Entity:User
Attr:id(Integer)
name(String)
userGroups(Set< UserGroup >)


下面是数据库表结构:
这里写图片描述
可以看到,t_usergroup_user作为中间表,里面有一个字段userGroupId作为外键指向了t_usergroup表,参考了该表的id,另一个外键userId指向了t_user表,参考了该表的id。这样的结构,和单向关联没区别,下面就看实体类的书写。


import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_usergroup")
public class UserGroup {

    private Integer id;
    private String name;
    private Set<User> users = new HashSet<User>();

    public UserGroup() {
        super();
    }

    public UserGroup(Integer id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToMany
    @JoinTable(name="t_usergroup_user",
            joinColumns={@JoinColumn(name="userGroupId")},
            inverseJoinColumns={@JoinColumn(name="userId")})
    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }


}

@JoinTable(name=”t_usergroup_user”中间表的名字
joinColumns={@JoinColumn(name=”userGroupId”)},中间表参考该实体id的那个外键的名称
inverseJoinColumns={@JoinColumn(name=”userId”)})对方实体在中间表中的名称

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {

    private Integer id;
    private String name;
    private Set<UserGroup> userGroups= new HashSet<UserGroup>();

    public User() {
        super();
    }

    public User(Integer id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToMany(mappedBy="users")
    public Set<UserGroup> getUserGroups() {
        return userGroups;
    }

    public void setUserGroups(Set<UserGroup> userGroups) {
        this.userGroups = userGroups;
    }


}

@ManyToMany(mappedBy=”users”)既然是双向关联,那么就要设置mappedBy属性,该属性指被UserGroup实体中的users这个属性映射。


实体类书写完毕后,我们来进行CRUD的测试
首先是添加数据的测试,testCreate()

     @Test
     public void testCreate(){
      Session session = sessionFactory.getCurrentSession();
      session.beginTransaction();

      UserGroup ug1 = new UserGroup();
      ug1.setName("超级管理员组");

      UserGroup ug2 = new UserGroup();
      ug2.setName("普通用户组");

      User u1 = new User();
      u1.setName("admin");

      User u2 = new User();
      u2.setName("wan");

      Set<User> userSet1 = new HashSet<User>();
      userSet1.add(u1);
      userSet1.add(u2);

      Set<User> userSet2 = new HashSet<User>();
      userSet2.add(u1);

      //超级管理员组只有一个admin
      ug1.setUsers(userSet2);

      //普通用户组包含两个用户
      ug2.setUsers(userSet1);

      session.saveOrUpdate(ug1);
      session.saveOrUpdate(ug2);
      session.saveOrUpdate(u1);
      session.saveOrUpdate(u2);

      session.getTransaction().commit();
     }

结果:
这里写图片描述
这里写图片描述
这里写图片描述


接下来是读取操作,testRead()

     @Test
     public void testRead(){
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();

         //用户组---->用户
         UserGroup ug = (UserGroup) session.load(UserGroup.class, 2);
         System.out.println("名称:"+ug.getName());
         for(User u : ug.getUsers()){
             System.out.println("包含了以下用户:"+u.getName());
         }

         //用户---->用户组
         User u = (User) session.load(User.class, 1);
         System.out.println("用户名称:"+u.getName());
         for(UserGroup ugg : u.getUserGroups()){
             System.out.println("在以下用户组中:"+ugg.getName());
         }

         session.getTransaction().commit();
     }

结果:

Hibernate: 
    select
        usergroup0_.id as id6_0_,
        usergroup0_.name as name6_0_ 
    from
        t_usergroup usergroup0_ 
    where
        usergroup0_.id=?
名称:普通用户组
Hibernate: 
    select
        users0_.userGroupId as userGrou1_1_,
        users0_.userId as userId1_,
        user1_.id as id7_0_,
        user1_.name as name7_0_ 
    from
        t_usergroup_user users0_ 
    left outer join
        t_user user1_ 
            on users0_.userId=user1_.id 
    where
        users0_.userGroupId=?
包含了以下用户:admin
包含了以下用户:wan
用户名称:admin
Hibernate: 
    select
        usergroups0_.userId as userId1_,
        usergroups0_.userGroupId as userGrou1_1_,
        usergroup1_.id as id6_0_,
        usergroup1_.name as name6_0_ 
    from
        t_usergroup_user usergroups0_ 
    left outer join
        t_usergroup usergroup1_ 
            on usergroups0_.userGroupId=usergroup1_.id 
    where
        usergroups0_.userId=?
在以下用户组中:超级管理员组
在以下用户组中:普通用户组

可以看到双向关联从哪边都可以找到另一边


接下来是修改操作,testUpdate()

     @Test
     public void testUpdate(){
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();

         UserGroup ug1 = (UserGroup) session.load(UserGroup.class, 1);
         ug1.setName("Super User Group");

         UserGroup ug2 = (UserGroup) session.load(UserGroup.class, 2);
         ug2.setName("Normal User Group");

         session.saveOrUpdate(ug1);
         session.saveOrUpdate(ug2);

         session.getTransaction().commit();
     }

结果:
这里写图片描述


最后是删除操作,testDelete()

     @Test
     public void testDelete(){
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();

         UserGroup ug2 = (UserGroup) session.load(UserGroup.class, 2);
         ug2.setUsers(null);

         session.delete(ug2);

         session.getTransaction().commit();
     }

结果:

Hibernate: 
    delete 
    from
        t_usergroup_user 
    where
        userGroupId=?
Hibernate: 
    delete 
    from
        t_usergroup 
    where
        id=?

这次我们看show sql出来的语句,先删除了中间表中的关系,再删除用户组,这样的操作是对的。


那么Hibernate关系映射系列就介绍到这里,希望对你有所帮助

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值