2

多くの複合キーを使用するデータベースでHibernateを使用しようとしていますが、それが多くの頭痛の種となっています。残念ながら、スキーマを変更することはできないため、フィールド間で多くの追加のマッピングを行う必要があります。JPA1.0およびHibernate3.3の使用に制限されています。

これまでの最大の問題は、2つの値の複合キーを使用して2つのエンティティを1対1で関連付けることです。この場合、テーブルにはこれらの列の名前が異なります(DBには、各列のテーブル固有のプレフィックス。)

クエリを実行するたびに、次の例外が発生します。

Caused by: org.hibernate.TypeMismatchException Provided id of the wrong type for class com.business.entity.InvestorIssuerEmailEntity.  
Expected: class com.business.entity.InvestorIssuerEmailEntityPK, got class com.business.entity.InvestorIssuerEntityPK; 

これらのテーブルの2つのクラス、InvestorIssuerEntityとInvestorIssuerEmailEntityには、オプションの@OneToOneアソシエーションがあります(場合によっては、InvestorIssuerにはInvestorIssuerEmailに一致するレコードがありません)。

@IdClass(InvestorIssuerEntityPK.class)
@Table(name = "T090_INVESTOR_ISSUER")
@Entity
InvestorIssuerEntity
    @Column(name = "T090_091_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long investorId;

    @Column(name = "T090_102_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long issuerId;

(other fields omitted)

    @OneToOne(optional = true)
    @JoinColumns(value = {
            @JoinColumn(name="T090_091_INVESTOR_ID", referencedColumnName = "T284_INVESTOR_ID", nullable = false, insertable = false, updatable = false),
            @JoinColumn(name = "T090_102_ISSUER_ID", referencedColumnName = "T284_ISSUER_ID", nullable = false, insertable = false, updatable = false)
    })
    @NotFound(action = NotFoundAction.IGNORE)
    private InvestorIssuerEmailEntity investorIssuerEmail;

... 

InvestorIssuerEntityPK 
    @Id
    @Column(name = "T090_091_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    private Long investorId;

    @Id
    @Column(name = "T090_102_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    private Long issuerId;

...

@IdClass(InvestorIssuerEmailEntityPK.class)
@Table(name = "T284_INVESTOR_ISSUER_EMAIL")
@Entity
InvestorIssuerEmailEntity
    @Column(name = "T284_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long investorId;

    @Column(name = "T284_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long issuerId;

...

InvestorIssuerEmailEntityPK 

    @Column(name = "T284_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long investorId;

    @Column(name = "T284_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long issuerId;  

2つのエンティティに@EmbeddableIdと同じクラスを使用し、次に次のように@AttributeOverridesを使用して、タイプの不一致の問題を回避しようとしました。

@Id
@EmbeddedId
@AttributeOverrides({
        @AttributeOverride(name = "investorId",
                column = @Column(name = "T284_INVESTOR_ID", nullable = false, insertable = true, updatable = true, length = 18, precision = 0)),
        @AttributeOverride(name = "issuerId",
                column = @Column(name = "T284_ISSUER_ID", nullable = false, insertable = true, updatable = true, length = 18, precision = 0))
})
private InvestorIssuerId investorIssuerId;

ただし、これら2つのエンティティに対してのみ変更を行い、他のエンティティには@IdClassアプローチを使用しました(エンティティに@IdClassまたは@EmbeddableIdのみを使用し、両方を使用しない場合ですか?)

「エンティティのマッピングで列が繰り返される」などの他の問題が発生したため、このアプローチに戻って、他の回避策があるかどうかを確認しました。

誰かがこの問題を回避するための解決策を持っていますか?StackOverflowを見回しましたが、関連付けで使用されている複合キーの名前が異なる場合はありません。

注: 以下の提案を試した後でも、次のエラーが発生します:org.hibernate.MappingException:エンティティのマッピングで繰り返される列:com.business.entity.InvestorIssuerEntity列:T090_091_INVESTOR_ID(insert = "false"update=でマッピングする必要があります「false」)

InvestorIssuerEntityからすべての関連付けを削除しても同じ問題が発生しました。エラーは、複合キークラスの@Columnアノテーションを削除したときにのみ解消されました。もちろん、investorIdがマップされていないため、クエリは機能しませんでした。複合キーを除いて、T090_091_INVESTOR_IDのすべての言及をすでに削除しているため、Hibernateが「マッピングで繰り返される列」を見つけた場所がわかりません。

InvestorIssuerEntityには、同じ主キーで結合を行う他の関連付けがありますが、関連付けられたエンティティには、複合キーに追加の列もあります。@EmbeddedIdを使用したら、それらをすべてのエンティティに使用することになっていますか?他のクラスには引き続き@IdClassを使用します。しかし、それではどのようにしてどこでも「繰り返し列」が発生するのでしょうか。

4

2 に答える 2

5

私はあなたのケースのための実用的な解決策を得たようです:

@Entity
public class InvestorIssuerEntity {
    @EmbeddedId 
    private InvestorIssuerEntityPK investorIssuerEntityPK;

    @OneToOne(optional=true, mappedBy="investorIssuerEntity")
    private InvestorIssuerEmailEntity investorIssuerEmailEntity;
}

@Entity
public class InvestorIssuerEmailEntity {
    @EmbeddedId @AttributeOverrides({
        @AttributeOverride(name="investorId", column=@Column(name="T02_INV_ID")),
        @AttributeOverride(name="issuerId", column=@Column(name="T02_ISS_ID"))
    })
    private InvestorIssuerEntityPK investorIssuerEntityPK;

    @OneToOne(optional=true) @PrimaryKeyJoinColumns({
        @PrimaryKeyJoinColumn(name="T02_ISS_ID", referencedColumnName="T01_ISS_ID"), 
        @PrimaryKeyJoinColumn(name="T02_INV_ID", referencedColumnName="T01_INV_ID")
    })
    private InvestorIssuerEntity investorIssuerEntity;
}

@Embeddable
public class InvestorIssuerEntityPK implements Serializable {
    private static final long serialVersionUID = -1176248537673293674L;

    @Column(name="T01_INV_ID")
    private Long investorId;

    @Column(name="T01_ISS_ID")
    private Long issuerId;
}

次のDDLが生成されます。これは、探しているもののようです。

create table InvestorIssuerEmailEntity (
    T02_INV_ID bigint not null,
    T02_ISS_ID bigint not null,
    primary key (T02_INV_ID, T02_ISS_ID)
)

create table InvestorIssuerEntity (
    T01_INV_ID bigint not null,
    T01_ISS_ID bigint not null,
    primary key (T01_INV_ID, T01_ISS_ID)
)

alter table InvestorIssuerEmailEntity 
    add constraint FKC2FBCC4E1E26612E 
    foreign key (T02_INV_ID, T02_ISS_ID) 
    references InvestorIssuerEntity
于 2011-01-07T14:27:23.757 に答える
0

別のアプローチについて言及したいと思います。

  • プロ:両方のエンティティが独自のPKクラスを使用できます
  • con:1:1の関係は、1つのエントリを持つセットに現れます

@OneToManyリレーションに切り替えて、関連するエンティティをセットに格納できます。セットには1つのエントリがあり、後処理ステップで解凍できます。

@OneToMany
@JoinColumns(value = {
        @JoinColumn(name="T090_091_INVESTOR_ID", referencedColumnName = "T284_INVESTOR_ID", nullable = false, insertable = false, updatable = false),
        @JoinColumn(name = "T090_102_ISSUER_ID", referencedColumnName = "T284_ISSUER_ID", nullable = false, insertable = false, updatable = false)
})
@NotFound(action = NotFoundAction.IGNORE)
private Set<InvestorIssuerEmailEntity> investorIssuerEmails;
于 2019-01-23T09:44:54.250 に答える