0

「Association」、「Account」、「Transaction」、「TransactionEvent」の4つのエンティティを一緒にマッピングします。AssociationのIDは単純な整数IDです。アカウントとトランザクションにはそれぞれ、アソシエーションと番号へのマッピングで構成されるIDが埋め込まれています。

TransactionEventには、1つのアカウントと1つのアソシエーションで構成される埋め込みIDが必要です。これで、それぞれがアソシエーションにマップされ、1つのTransactionEventで同じアソシエーションになりたいと思います。

JPAアノテーションはHibernateマッピングに使用されますが、これを機能させることはできません。アソシエーションキーに同じ列名を強制しようとしましたが、Hibernateが列の繰り返しについて文句を言います。

これを解決することは可能ですか、それとも私はまっすぐに考えていませんか?

アノテーションが付けられたクラスは次のとおりですが、getter / setterと非id列、javax.persistence名前空間からのアノテーションを削除しました。


@Entity
public class Association implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
}

@Embeddable
public class AccountPK implements Serializable {
    @ManyToOne(optional=false)
    private Association association;

    @Column(nullable=false)
    private int number;
}

@Embeddable
public class TransactionPK implements Serializable {
    @ManyToOne
    private Association association;

    @GeneratedValue(strategy=GenerationType.AUTO)
    private long number;
}

@Embeddable
public class AccountEventPK implements Serializable {
    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="association_id", referencedColumnName="association_id"),
        @JoinColumn(name="account_number", referencedColumnName="number")
    })
    private Account account;

    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="association_id", referencedColumnName="association_id"),
        @JoinColumn(name="transaction_number", referencedColumnName="number")
    })
    private Transaction transaction;
}

実際のアカウント、トランザクション、およびAccountEventエンティティはフォームにあります


@Entity
public class Account implements Serializable {
        @EmbeddedId
        private AccountPK id;
}
4

1 に答える 1

2

これは JPA ではサポートされていませんが、Hibernate 固有であるため、埋め込み id コンポーネントに関連付けを直接配置する経験はあまりありません。

別の方法として、JPA wikibookのComposite Primary Keysセクションで説明されているアプローチを使用することをお勧めします。

(...) JPA 1.0 では、すべての@Id マッピングがマッピングである必要があるため、ID がor マッピングBasicを介して外部キー列から取得される場合、外部キー列の Basic @Id マッピングも定義する必要があります。この理由の一部は、Id が ID とキャッシングの目的で、 またはAPI で使用するための単純なオブジェクトである必要があるためです。OneToOneManyToOneIdClassEntityManager find()

同じ外部キー列に対して 2 つのマッピングが存在するため、どちらをデータベースに書き込むかを定義する必要があります (基本的なものである必要があります)。そのため、外部キーOneToOneまたはManyToOne 外部キーは読み取り専用として定義する必要があります。これは、JoinColumn属性 insertableupdatableを false に設定するか、 の @PrimaryKeyJoinColumn代わりに を 使用して行い@JoinColumnます。

同じ列に対して 2 つのマッピングを持つことの副作用は、2 つの同期を維持する必要があることです。これは通常、OneToOne属性の set メソッドで Basic 属性値をターゲット オブジェクトの ID に設定することによって行われます。ターゲット オブジェクトの主キーが の場合、これは非常に複雑になる可能性が GeneratedValueあります。この場合、2 つのオブジェクトを関連付ける前に、ターゲット オブジェクトの ID が割り当てられていることを確認する必要があります。

(...)

ManyToOneid アノテーションの例

...
@Entity
@IdClass(PhonePK.class)
public class Phone {
    @Id
    @Column(name="OWNER_ID")
    private long ownerId;

    @Id
    private String type;

    @ManyToOne
    @PrimaryKeyJoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...

    public void setOwner(Employee owner) {
        this.owner = owner;
        this.ownerId = owner.getId();
    }
    ...
}

これはあなたが探しているもののようです(そしておそらくそれほど複雑ではありません)。このソリューションを(段階的に)実装しようと思います。

于 2010-09-21T22:37:24.773 に答える