2つのエンティティ間で1対1をマッピングしているときに、以下の例外が発生しました。最初の1つのエンティティには、複合キーが埋め込まれています。 2番目のエンティティにも複合キーが埋め込まれています。テーブルはレガシーシステムの一部です。データはフラットで、関係は明確に定義されていません。助けてください。
Caused by: org.hibernate.AnnotationException: referencedColumnNames(FLAG_NAME) of net.javabeat.spring.model.ReferralsM.mnEditFlag referencing net.javabeat.spring.model.MnEditFlag not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.Java:205)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.Java:116)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.Java:1515)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.Java:1440)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.Java:1358)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:1727)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:1778)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.Java:247)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.Java:373)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.Java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1509)
... 34 more
これがメイン/親テーブルでの1対1のマッピングです。
@OneToOne(targetEntity = MnEditFlag.class, fetch = FetchType.LAZY)
@JoinColumn(name = "REFFLG", referencedColumnName = "FLAG_NAME", insertable = false, updatable = false)
MnEditFlag mnEditFlag;
この問題の原因は、参照されているエンティティのIDが複数の列で定義されているのに、単一の結合列を使用しようとしていることです。必要なすべての参加列を定義するだけで、次のことができます。
@JoinColumns({
@JoinColumn(name = "REFFLG", referencedColumnName = "FLAG_NAME"),
@JoinColumn(name = "OTHER_KEY", referencedColumnName = "SOME_OTHER_NAME"))
...
})
MnEditFlag mnEditFlag;
OT:targetEntity
アノテーションにOneToOne
属性は必要ありません。これは、ターゲットエンティティのタイプMnEditFlag
によってすでに定義されています。おそらく、型指定されていないtargetEntity
に対してのみCollections
が必要です。
編集:PKの一部にすぎない単一の結合列があり、既存のテーブルを変更できない場合は、必要なすべての列を使用して新しい結合テーブルを定義できます。
次に、関係に使用する結合テーブルを定義します。
@JoinTable(name="ReferralsM_MnEditFlag",
joinColumns={
@JoinColumn(name="REFERRALS_ID1", referencedColumnName="ID1"),
@JoinColumn(name="REFERRALS_ID2", referencedColumnName="ID2")
}, inverseJoinColumns={
@JoinColumn(name="REFFLG", referencedColumnName="FLAG_NAME"),
@JoinColumn(name="REFFLG2", referencedColumnName="FLAG_NAME2")
})
MnEditFlag mnEditFlag;
プログラムまたはクエリによって、データを新しい結合テーブルに移行する必要があります。
残念ながら、Vanilla JPAを使用して部分PKとの関係を定義することはできません。おそらく、Hibernateにはクエリによる1対1のような機能がありますが、確認できません。
EDIT2:完全に機能するには、結合テーブルに両方のエンティティのすべてのPK列が含まれている必要があります。そのため、この例では、両側に2つの結合列を定義しました。列の数とその名前は、純粋に例示的なものです。
テーブルにすでにある結合列を1つだけ抽出しても、値は追加されません。
最適な解決策は、エンティティテーブルを変更して、エンティティ間の適切な関係を定義することです。テーブルの1つだけを変更し、それを所有側として定義するだけで十分ですが、すべてのFK列を使用します。上記のように欠落しているFK列のデータを追加する必要があるため、これには移行作業が必要になります。
EDIT3:私が推奨した戦略は、完全なCRUD機能を持たせたいという主張に基づいていました。表示またはレポート用にデータをプルするだけの場合は、ビューはまったく問題ありません。必要な列を定義し、ビュー全体を単一のエンティティにマップできます。ただし、ビューであるため、データを変更したり、移行したりすることはできません。
@ManyToOneでtargetEntityを使用できます。 targetEntityは、親(おそらく抽象)クラスと同じである必要があります。一時的な解決策は、クラス階層に応じてここにあります: https://hibernate.atlassian.net/browse/HHH-4975