1. 程式人生 > >Hibernate關係對映(六)多對多單向關聯@ManyToMany Annotation方式

Hibernate關係對映(六)多對多單向關聯@ManyToMany Annotation方式

本篇介紹多對多的單向關聯,多對多的處理方式是,有一張中間表,中間表儲存兩個多方之間的關係。首先來看實際應用場景:在之前開發的系統中,應用了基於角色的控制訪問,也就是RBAC模型,一個使用者可能存在多種角色,一種角色也可能有多個使用者,所以使用者和角色之間是一個多對多的關係。實體:使用者(User),具有如下屬性:Id,名稱(name),角色列表(roles);實體:角色(Role),具有如下屬性:Id,名稱(name);既然是單項關聯,所以就可以從當前使用者,讀取到具有的角色列表,而不能從當前角色獲取使用者列表。

下面來看錶結構:
這裡寫圖片描述
中間表user_role中,有一個欄位userId作為外來鍵指向了user表的id,同樣,有一個欄位roleId也是作為外來鍵指向了role表的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;

@Entity
public class
User {
private Integer id; private String name; private Set<Role> roles = new HashSet<Role>(); 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 @JoinTable(name="user_role", joinColumns={@JoinColumn(name="userId")}, inverseJoinColumns={@JoinColumn(name="roleId")}) public Set<Role> getRoles() { return roles; } public void setRoles(Set<Role> roles) { this.roles = roles; } }

用一個Set集合來儲存User中的Role列表,@ManyToMany表示這是一個多對多關係@JoinTable用來設定中間表,name=”user_role”中間表的名稱,joinColumns={@JoinColumn(name=”userId”)},設定當前實體在中間表中的對映,也就是說在中間表中設定一個欄位叫userId,指向當前user表的id;inverseJoinColumns={@JoinColumn(name=”roleId”)}設定對方實體在中間中的對映,也就是說在中間表中設定一個欄位roleId,指向對方表(role表)的id。

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

@Entity
public class Role {

    private Integer id;
    private String name;



    public Role() {
        super();
    }


    public Role(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;
    }



}

role表就沒什麼要介紹的了。

下面來看CRUD測試:
首先是新增資料的測試,testCreate()

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

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

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

      Role r1 = new Role();
      r1.setName("超級管理員");

      Role r2 = new Role();
      r2.setName("普通使用者");

      Set<Role> roleSet1 = new HashSet<Role>();
      roleSet1.add(r1);
      roleSet1.add(r2);

      u1.setRoles(roleSet1);


      Set<Role> roleSet2 = new HashSet<Role>();
      roleSet2.add(r2);

      u2.setRoles(roleSet2);

      session.saveOrUpdate(u1);
      session.saveOrUpdate(u2);
      session.saveOrUpdate(r1);
      session.saveOrUpdate(r2);

      session.getTransaction().commit();
     }

新建一個u1,叫admin,一個u2,叫wan
新建一個r1,叫“超級管理員”,一個r2,叫“普通使用者”
new一個角色集合,包含了r1和r2,設定給u1
new一個角色集合,只包含r2,設定給u2
將上述內容,儲存到資料庫,就是本測試用例。
那麼,在資料庫中,中間表應該有三條資料
userId roleId
1 1
1 2
2 2
結果如下:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

接下來進行讀取資料的測試,testRead()

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

         User user = (User) session.load(User.class, 1);
         System.out.println(user.getName());
         for (Role r:user.getRoles()){
             System.out.println(r.getName());
         }


         session.getTransaction().commit();
     }

結果如下:

Hibernate: 
    select
        user0_.id as id6_0_,
        user0_.name as name6_0_ 
    from
        User user0_ 
    where
        user0_.id=?
admin
Hibernate: 
    select
        roles0_.userId as userId1_,
        roles0_.roleId as roleId1_,
        role1_.id as id7_0_,
        role1_.name as name7_0_ 
    from
        user_role roles0_ 
    left outer join
        Role role1_ 
            on roles0_.roleId=role1_.id 
    where
        roles0_.userId=?
超級管理員
普通使用者

下面是修改操作,testUpdate()

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

         User user = (User) session.load(User.class, 2);
         user.setName("administrator");

         Role role = (Role) session.load(Role.class, 1);
         Set<Role> roleSet = new HashSet<Role>();
         roleSet.add(role);

         user.setRoles(roleSet);

         session.saveOrUpdate(user);


         session.getTransaction().commit();
     }

將使用者為wan讀取出來,修改名字為administrator,將普通使用者的角色修改為超級管理員,結果如下:
這裡寫圖片描述
這裡寫圖片描述

最後是刪除操作,testDelete()

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

         User user = (User) session.load(User.class, 2);
         user.setRoles(null);

         session.delete(user);

         session.getTransaction().commit();
     }

結果:
這裡寫圖片描述
這裡寫圖片描述

下一篇介紹多對多的雙向關聯,希望對你有所幫助