2017-02-20 45 views
0

嗨我是春季JPA和春季安全新手,我花了一段時間嘗試根據用戶和角色進行認證工作。春季JPA用戶,角色認證 - 我如何避免重複的角色條目?

用戶應該能夠擁有許多角色,並且角色可以屬於許多用戶。

應該只有大約4個角色。

我試圖用@Manytomany映射和連接表來實現這一點。

它或多或少的作品,但是當我試圖用一組角色堅持一個新用戶時,它會向角色表中添加重複的條目(或者如果我在角色表上放置一個唯一鍵擊中英國違規) 。

下面的代碼:

用戶

import java.util.Set; 

import javax.persistence.*; 

@Entity 
public class User { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    private String email; 

    private String password; 

    public long getId() { 
     return id; 
    } 

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

    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public Set<Role> getRoles() { 
     return roles; 
    } 

    public void setRoles(Set<Role> roles) { 
     this.roles = roles; 
    } 

    @ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL) 
    @JoinTable(joinColumns = @JoinColumn(name = "id"),inverseJoinColumns = @JoinColumn(name = "roleId")) 
    private Set<Role> roles; 

    public User(String email, String password, Set<Role> roles) { 
     super(); 
     this.email = email; 
     this.password = password; 
     this.roles = roles; 
    } 

} 

作用

import java.util.Set; 

import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.ManyToMany; 

@Entity 
public class Role { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    private String role; 

    @ManyToMany(mappedBy = "roles",fetch = FetchType.LAZY) 
    private Set<User> users; 

    public Role(String role) { 
     super(); 
     this.role = role; 
    } 

    public long getId() { 
     return id; 
    } 

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

    public String getRole() { 
     return role; 
    } 

    public void setRole(String role) { 
     this.role = role; 
    } 

    public Set<User> getUsers() { 
     return users; 
    } 

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



} 

回答

1

ManyToMany是正確的邏輯關係類型。您得到太多角色的原因可能是您創建了角色的新實例,但是如果角色已經存在於數據庫中,則必須將其加載到持久性上下文中,並且只有在角色不存在時才創建新角色。

如果您在代碼中管理事務,如果您使用帶有@Transactional的容器管理持久性,則應該刪除事務代碼和try-finally塊,這看起來像這樣。

try { 
    List<String> roleNames = Lists.newArrayList("user, admin, superuser"); 
    User user = new User("Peter", "Pan"); 
    List<Role> roles = new ArrayList<>(); 
    entityManager.getTransaction().begin(); 
    for (String roleName : roleNames) { 
     List<Role> found = entityManager.createQuery("select r from Roles r where r.name = :roleName", Role.class) 
       .setParameter("roleName", roleName).getResultList(); 
     if (found.isEmpty()) { 
      Role role = new Role(roleName); 
      entityManager.persist(role); 
      roles.add(role); 
     } else { 
      roles.addAll(found); 
     } 
    } 
    user.setRoles(roles); 
    entityManager.persist(user); 
    entityManager.getTransaction().commit(); 
} finally { 
    entityManager.close(); 
} 

個人而言,我幾乎從來不使用JPA的ManyToMany,我一般把它歸結爲2個OneToMany關係,這樣,我有一個實體,其另有奇蹟般地創造JPA映射表。這也爲您提供了額外的控制,例如,如果您需要修改或刪除用戶的角色,則可以直接刪除UserRoleMapping實體,而不必操作Role和User的列表。它還可以讓您更好地控制級聯。

+0

謝謝,我接受了第二部分的建議,並使它成爲兩個一對多關係,使user_roles成爲一個實體,併爲用戶提供了一個簡單的枚舉類型 –

相關問題