質問

テーブルuser_rolesが2つの列(userID、roleID)を複合主キーとして定義するようにする方法。簡単である必要があります。思い出すことも見つけることもできません。

user エンティティ:

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles")
public List<RoleDAO> getRoles() {
    return roles;
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getUserID() {
    return userID;
}

roles エンティティ:

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles")
public List<UserDAO> getUsers() {
    return users;
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getRoleID() {
    return roleID;
}

ありがとう。

**詳細

3番目のテーブル user_roles (上記で自動生成)があり、 user エンティティと roleID roles エンティティからのcode>。ここで、生成されたテーブル( user_roles )のこれらの2つの列を複合主キーにする必要があります。

役に立ちましたか?

解決

質問通りに行う方法については、すでにいくつかの良い回答があります。

参考のために、代わりにHibernateでこれを行う推奨方法、つまりサロゲートキーをプライマリキーとして使用し、ビジネスキーをNaturalIdとしてマークする方法について説明します。

  

の使用をお勧めしますが   主キーとしての代理キー、あなた   自然なキーを識別しようとする必要があります   すべてのエンティティに対して。自然な鍵は   プロパティまたはプロパティの組み合わせ   それは一意であり、nullではありません。それは   また不変です。のプロパティをマップする   内部の自然な鍵    素子。 Hibernateは   必要な一意のキーを生成し、   nullability制約、および   結果、マッピングはより多くなります   自己文書化。

     

実装することをお勧めします   equals()とhashCode()で比較します   エンティティの自然キープロパティ。

注釈を使用したコードでは、これは次のようになります。

@Entity
public class UserRole {
  @Id
  @GeneratedValue
  private long id;

  @NaturalId
  private User user;
  @NaturalId
  private Role role;
}

これを使用すると、作成された主キーを頻繁に参照/マッピングする必要があるときにわかるように、今後の多くの頭痛の種を節約できます。

これは難しい方法であることがわかり、最終的にはHibernateとの戦いをあきらめ、代わりにフローを使用することにしました。レガシーソフトウェアや依存関係を扱っている可能性があるため、これはあなたのケースでは不可能かもしれないことを完全に理解していますが、今後の参考のために言及したいだけです。 (使用できない場合は、おそらく他の誰かが使用できる!)

他のヒント

要件を満たすために、@ ManyToManyを@OneToManyマッピングとしてマッピングできます。 これにより、USER_ROLEには、複合主キーとしてUSER_IDとROLE_IDの両方が含まれます

次の方法を説明します:

@Entity
@Table(name="USER")
public class User {

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="joinedUserRoleId.user")
    private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();

    // no-arg required constructor
    public User() {}

    public User(Integer id) {
        this.id = id;
    }

    // addRole sets up bidirectional relationship
    public void addRole(Role role) {
        // Notice a JoinedUserRole object
        JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(this, role));

        joinedUserRole.setUser(this);
        joinedUserRole.setRole(role);

        joinedUserRoleList.add(joinedUserRole);
    }

}

@Entity
@Table(name="USER_ROLE")
public class JoinedUserRole {

    public JoinedUserRole() {}

    public JoinedUserRole(JoinedUserRoleId joinedUserRoleId) {
        this.joinedUserRoleId = joinedUserRoleId;
    }

    @ManyToOne
    @JoinColumn(name="USER_ID", insertable=false, updatable=false)
    private User user;

    @ManyToOne
    @JoinColumn(name="ROLE_ID", insertable=false, updatable=false)
    private Role role;

    @EmbeddedId
    // Implemented as static class - see bellow
    private JoinedUserRoleId joinedUserRoleId;

    // required because JoinedUserRole contains composite id
    @Embeddable
    public static class JoinedUserRoleId implements Serializable {

        @ManyToOne
        @JoinColumn(name="USER_ID")
        private User user;

        @ManyToOne
        @JoinColumn(name="ROLE_ID")
        private Role role;

        // required no arg constructor
        public JoinedUserRoleId() {}

        public JoinedUserRoleId(User user, Role role) {
            this.user = user;
            this.role = role;
        }

        public JoinedUserRoleId(Integer userId, Integer roleId) {
            this(new User(userId), new Role(roleId));
        }

        @Override
        public boolean equals(Object instance) {
            if (instance == null)
                return false;

            if (!(instance instanceof JoinedUserRoleId))
                return false;

            final JoinedUserRoleId other = (JoinedUserRoleId) instance;
            if (!(user.getId().equals(other.getUser().getId())))
                return false;

            if (!(role.getId().equals(other.getRole().getId())))
                return false;

            return true;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 47 * hash + (this.user != null ? this.user.hashCode() : 0);
            hash = 47 * hash + (this.role != null ? this.role.hashCode() : 0);
            return hash;
        }

    }

}

記憶する

  

オブジェクトに割り当てられている場合   識別子、または複合キー、   識別子は   save()を呼び出す前のオブジェクトインスタンス。

それで、これを処理するために、このようなJoinedUserRoleIdコンストラクターを作成しました

public JoinedUserRoleId(User user, Role role) {
    this.user = user;
    this.role = role;
}

そして最後にRoleクラス

@Entity
@Table(name="ROLE")
public class Role {

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="JoinedUserRoleId.role")
    private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();

    // no-arg required constructor
    public Role() {}

    public Role(Integer id) {
        this.id = id;
    }

    // addUser sets up bidirectional relationship
    public void addUser(User user) {
        // Notice a JoinedUserRole object
        JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(user, this));

        joinedUserRole.setUser(user);
        joinedUserRole.setRole(this);

        joinedUserRoleList.add(joinedUserRole);
    }

}

テストに従って、次のように書きましょう

User user = new User();
Role role = new Role();

// code in order to save a User and a Role
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Serializable userId  = session.save(user);
Serializable roleId = session.save(role);

session.getTransaction().commit();
session.clear();
session.close();

// code in order to set up bidirectional relationship
Session anotherSession = HibernateUtil.getSessionFactory().openSession();
anotherSession.beginTransaction();

User savedUser = (User) anotherSession.load(User.class, userId);
Role savedRole = (Role) anotherSession.load(Role.class, roleId);

// Automatic dirty checking
// It will set up bidirectional relationship
savedUser.addRole(savedRole);

anotherSession.getTransaction().commit();
anotherSession.clear();
anotherSession.close();

上記のコードによると、JoinedUserRoleクラスへの参照はありません。

JoinedUserRoleを取得する場合は、次を試してください

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Integer userId;
Integer roleId;

// Lets say you have set up both userId and roleId
JoinedUserRole joinedUserRole = (JoinedUserRole) session.get(JoinedUserRole.class, new JoinedUserRole.JoinedUserRoleId(userId, roleId));

// some operations

session.getTransaction().commit();
session.clear();
session.close();

よろしく、

複合キーは@IdClassを使用して実行されます(他の方法は、@ EmbeddedIdと@Embeddableを使用して、どちらを探しているかわからない)@IdClassは次のとおりです

@Entity
@IdClass(CategoryPK.class)
public class Category {
    @Id
    protected String name;

    @Id
    protected Date createDate;

}

public class CategoryPK implements Serializable {

    String name;

    Date createDate;

    public boolean equals(object other) {
        //implement a equals that the PP can use to determine 
        //how the CategoryPK object can be identified.
    }

    public int hashCode(){
        return Super.hashCode();
    }
}

ここでの私のカテゴリはあなたのuser_rolesであり、名前とcreateDateはあなたのuseridとroleidです

質問を改善していただきありがとうございます...そして提案を考慮に入れてください。

(申し訳ありませんが、エンティティをDaosで後置するのは少し奇妙ですが、それはポイントではありません。)

問題が残っているかどうかわからない:

  • 説明する2つのエンティティにはそれぞれ、ペアではなく1つのPKがあります。
  • リンクテーブルには対応するエンティティがありません。2つのエンティティとそのManyToMany関係によって暗黙的に定義されます。 3番目のエンティティが必要な場合は、OneToManyとManyToOneのリレーションシップのペアのManyToManyを変更します。

主キーでも同じ問題が発生しました。 また、@ Embeddableクラスと@EmbeddedIdクラスを使用したソリューションも知っていました。しかし、私は注釈付きのシンプルなソリューションが欲しかった。

この記事で啓発を見つけました: http:// www .vaannila.com / hibernate / hibernate-example / hibernate-mapping-many-to-many-using-annotations-1.html

そしてここに魔法があります:

これにより、結合テーブルに主キーが生成されます。

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="classA_classB")
private Set<ClassA> classesA;

これは、結合テーブルに主キーを生成しません:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="classA_classB")
private List<ClassA> classesA;

少なくとも私の環境では

違いは、設定またはリスト

を使用していることに注意してください
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top