2012-04-22 88 views
7

我有一個非常標準的場景,我有一個用user_id作爲PK的用戶表和一個role_id作爲PK的角色表。這兩個表通過多對多的關係相關聯(即用戶可以有很多角色,角色可以應用於許多用戶),隨後我有一個名爲users_has_roles的連接表。 users_has_roles中只有兩列是users_user_id和roles_role_id。JPA堅持多到很多

我已經生成了實體類(見下文),並且我沒有問題將數據保存到用戶和角色表中,但是我失敗了,無法將任何東西持久保存到users_has_roles連接表中,所以當前沒有我的用戶被分配角色。在我瘋狂之前,有人可以讓我擺脫痛苦,告訴我應該如何將users_user_id和相應的roles_role_id添加到users_has_roles表中,以便我的用戶可以擁有角色?

我Users.java實體類:

@Entity 
@Table(name = "users") 
@XmlRootElement 
@NamedQueries({ 
@NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"), 
@NamedQuery(name = "Users.findByUserId", query = "SELECT u FROM Users u WHERE u.userId = :userId"), 
@NamedQuery(name = "Users.findByUsername", query = "SELECT u FROM Users u WHERE u.username = :username"), 
@NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password")}) 
public class Users implements Serializable { 
private static final long serialVersionUID = 1L; 
@Id 
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 60) 
@Column(name = "user_id") 
private String userId; 
@Basic(optional = false) 
@NotNull 
@Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email") 
@Size(min = 1, max = 45) 
@Column(name = "username") 
private String username; 
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 120) 
@Column(name = "password") 
private String password; 
@JoinTable(name = "users_has_roles", joinColumns = { 
    @JoinColumn(name = "users_user_id", referencedColumnName = "user_id")}, inverseJoinColumns = { 
    @JoinColumn(name = "roles_role_id", referencedColumnName = "role_id")}) 
@ManyToMany 
private Collection<Roles> rolesCollection; 
@OneToMany(cascade = CascadeType.ALL, mappedBy = "usersUserId") 
private Collection<UserAccount> userAccountCollection; 
@OneToMany(cascade = CascadeType.ALL, mappedBy = "usersUserId") 
private Collection<UserDetails> userDetailsCollection; 

... 

All the getter and setter methods etc. 

我Roles.java實體類:

@Entity 
@Table(name = "roles") 
@XmlRootElement 
@NamedQueries({ 
@NamedQuery(name = "Roles.findAll", query = "SELECT r FROM Roles r"), 
@NamedQuery(name = "Roles.findByRoleId", query = "SELECT r FROM Roles r WHERE r.roleId = :roleId"), 
@NamedQuery(name = "Roles.findByRoleName", query = "SELECT r FROM Roles r WHERE r.roleName = :roleName"), 
@NamedQuery(name = "Roles.findByRolePermission", query = "SELECT r FROM Roles r WHERE r.rolePermission = :rolePermission"), 
@NamedQuery(name = "Roles.findByRoleDescription", query = "SELECT r FROM Roles r WHERE r.roleDescription = :roleDescription")}) 
public class Roles implements Serializable { 
private static final long serialVersionUID = 1L; 
@Id 
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 60) 
@Column(name = "role_id") 
private String roleId; 
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 45) 
@Column(name = "role_name") 
private String roleName; 
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 45) 
@Column(name = "role_permission") 
private String rolePermission; 
@Size(max = 45) 
@Column(name = "role_description") 
private String roleDescription; 
@ManyToMany(mappedBy = "rolesCollection") 
private Collection<Users> usersCollection; 

... 

All the getter and setter methods etc. 

感謝

---- ---- UPDATE

// New Users 
Users currentUser = new Users(); 
currentUser.setUserId(userId); 
currentUser.setUsername(email); 
currentUser.setPassword(password); 
getUsersFacade().create(currentUser); 

回答

6

你的例子工作正常(EclipseLink 2.3,MySQL)。可能的問題是你沒有顯示的部分代碼。例如,在rolesCollection中添加元素。典型的錯誤是例如僅將元素添加到非擁有方。

對於堅持它,你必須保持關心持有端(一個沒有的mappedBy),也爲保持在內存中的對象圖與數據庫一致的關係,你應該隨時修改關係的兩側。

我有以下試了一下:

// method to add element to rolesCollection 
    public void addRoles(Roles r) { 
     rolesCollection.add(r); 
    } 

    //first created new instances of Users and Roles 
    // then: 
    tx.begin(); 
    users.addRoles(r); 
    //it is not needed for persisting, but here you can also 
    //add user to roles. 
    em.persist(users); 
    em.persist(r); 
    tx.commit(); 
+1

米克你好,我是仍然困惑!我不明白上面的代碼是如何工作的。如果我需要修改關係的兩側,我是否需要向rolesCollection和usersCollection添加元素?它看起來像你只是添加到rolesCollection。此外,我很困惑我將添加到相應的集合。 rolesCollection是否同時需要一個users_user_id和一個roles_role_id? – tarka 2012-04-22 10:01:39

+0

事情是:要堅持數據庫,最低要求是修改擁有方(一個沒有mappedBy)。不好的一點是,那麼與mappedBy的收集不同步。這就是爲什麼通常更好地修改雙方,這意味着將兩個角色添加到rolesCollection和rolesCollection。 – 2012-04-22 10:06:36

+0

好吧,所以最好的做法是將兩個元素添加到兩個集合中,但是我要向每個集合添加什麼元素?添加一個user_id和一個role_id兩個? – tarka 2012-04-22 10:15:04

8

好第一關感謝米克領導我的答案。我只是想發佈一個答案,可能會直接有助於任何其他人可能處於我的位置。這也是基於尤里卡時刻,所以它可能不是技術上正確的,但這是我的看法。

我面臨的最大問題是,在MySQL中,我可以將橋接表視爲單個表! (對不起,我無法發佈我的EER圖的圖像,但目前我似乎沒有足夠的特權)所以我認爲Java也會將橋接表視爲表!那麼它不會。這個橋接表並不是真正存在於Java中的,它實際上是由與之相關聯的相對錶集合類型表示的。

看到它,我是徹底忘記橋接表,集中在兩個「真正」的表,並在這些數據關聯的最簡單方法。下面的代碼並不是最好的實踐,因爲我只是設置了role_id,但只是爲了顯示我的觀點就沒有問題。

List<Roles> userRoleList = new ArrayList<Roles>(); 

Users currentUser = new Users(); 
currentUser.setUserId(userId); 
currentUser.setUsername(email); 
currentUser.setPassword(password); 

Roles userRole = new Roles(); 
userRole.setRoleId("2"); 

userRoleList.add(userRole); 
currentUser.setRolesCollection(userRoleList); 

getUsersFacade().create(currentUser); 

希望能幫助任何正在與多對多關係掙扎的人。

(NB。我已經編輯了原來的問題代碼使用列表,而不是爲了便於集合,但你可以只以及使用適合您需要的任何其他類型的。)