8

私は、PK として user_id を持つユーザーのテーブルと、PK として role_id を持つロールのテーブルを持つ、かなり標準的なシナリオを持っています。2 つのテーブルは多対多の関係 (つまり、ユーザーは多くのロールを持つことができ、ロールは多くのユーザーに適用できます) によって関連付けられており、その後、users_has_roles という結合テーブルがあります。users_has_roles の 2 つの列は、users_user_id と roles_role_id だけです。

エンティティ クラスを生成し (以下を参照)、ユーザー テーブルとロール テーブルにデータを永続化するのに問題はありませんが、テーブルに参加している users_has_roles に無残に何かを永続化することに失敗したため、現在、ユーザーにロールが割り当てられていません。私が頭がおかしくなる前に、誰かが私を悲惨な状況から解放し、対応する roles_role_id を持つ users_user_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.

ありがとう

- - アップデート - -

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

2 に答える 2

9

まず最初に、私を答えに導いてくれた Mikko に感謝します。私がいた立場にいる可能性のある他の人に直接役立つ可能性のある回答を投稿したかっただけです。また、これはエウレカの瞬間に基づいているため、技術的に正しくない可能性がありますが、これが私の見方です。

私が直面している大きな問題は、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);

多対多の関係で苦労している他の人の助けになることを願っています.

(注: 元の質問コードを編集して、コレクションの代わりにリストを使用するようにしましたが、必要に応じて他のタイプを使用することもできます。)

于 2012-04-22T16:55:17.550 に答える
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();
于 2012-04-22T09:10:04.433 に答える