2012-04-22 11 views
7

私はPKのuser_idとrole_idを持つロールのテーブルを持つPKのテーブルを持っています。 2つのテーブルは、多対多の関係(つまり、ユーザーは多数のロールを持つことができ、ロールは多数のユーザーに適用できます)と関連しており、その後users_has_rolesという結合テーブルがあります。 users_has_rolesの2つのカラムは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

+0

事は次のとおりです:makeはデータベースに永続化され、最低限必要なのは所有側(mappedByなし)を変更することです。悪い点は、mappedByのコレクションが同期していないことです。そのため、両側を変更する方が一般的に適しています。これは、rolesCollectionとrolesCollectionの両方に要素を追加することを意味します。 –

+0

これで、両方のコレクションに要素を追加するのがベストプラクティスですが、各コレクションには何を追加しますか?両方にuser_idとrole_idの両方を追加しますか? – tarka

8

[OK]を最初に。私はちょうど私がいた立場にいる可能性のある他の誰かに直接役立つかもしれない答えを投稿したかったのです。またこれはユーレカの瞬間に基づいていますので、それは技術的には正しくないかもしれませんが、

私が直面している大きな問題は、MySQLではブリッジテーブルを個別のテーブルとして見ることができたことです。 (申し訳ありませんが、私はEERの図を掲載することができませんが、今は十分な特権を持っていないようです)だから、私はJavaがテーブルとしてテーブルを参照することも想定していました!まあそれはしません。そのブリッジング・テーブルは、従来のテーブルとしてJavaには実際には存在しません。これは、実際には、それに関連付けられている反対側のテーブル・コレクション・タイプによって表されます。

私にとって最も簡単な方法は、ブリッジテーブルを完全に忘れて、2つの「実際の」テーブルに集中し、それらのデータを関連付けることでした。次のコードは、私が単に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。私の代わりに容易にするためにコレクションのリストを使用するために元の質問のコードを編集したあなただけのようにも、あなたのニーズに合う他のタイプを使用することができます。)

関連する問題