2011-08-10 4 views
13

Hibernate hbm.xmlファイルのいくつかのクラスをJPAアノテーションに移行しています。Hibernate/JPAでケースごとに@Embeddedプロパティからフィールドを除外する

埋め込み可能なクラスAddressがいくつかの場所で使用されています。各場所では、Addressのプロパティの異なるサブセットが使用されます。この不自然な例では、のShippingAddressがAddress.countryを使用するが、billingAddressがないこと

(ゲッター/セッターは、簡潔にするために省略)

@Embeddable 
public class Address { 
    String email; 
    String address; 
    String city; 
    String state; 
    String zip; 
    String country; 
} 

@Entity 
@Table(name="customer") 
public class Customer { 
    @Embedded 
    @AttributeOverrides({ 
    @AttributeOverride(name="address", [email protected](name="ship_addr"), 
    @AttributeOverride(name="city", [email protected](name="ship_city"), 
    @AttributeOverride(name="state", [email protected](name="ship_state"), 
    @AttributeOverride(name="zip", [email protected](name="ship_zip"), 
    @AttributeOverride(name="country", [email protected](name="ship_country") 
    }) 
    Address shippingAddress; 

    @Embedded 
    @AttributeOverrides({ 
    @AttributeOverride(name="address", [email protected](name="bill_addr"), 
    @AttributeOverride(name="city", [email protected](name="bill_city"), 
    @AttributeOverride(name="state", [email protected](name="bill_state"), 
    @AttributeOverride(name="zip", [email protected](name="bill_zip") 
    }) 
    Address billingAddress; 
} 

注意。どちらもAddress.emailを使用していません。

Hibernateは、私が明示的に提供していないカラムに対して@Columnタグを推測しているという問題があります。

@TransientをすべてのAddressフィールドに追加しようとしましたが、@AttributeOverride@Transientには表示されません。

これに対応する方法はありますか?

答えて

6

埋め込みオブジェクトのフィールドのアドレスを「無視」することはアノテーションでは考えられません。

回避策は、電子メールのない基本タイプのアドレスと、フィールドemailを持つExtendedAddress(Addressのサブクラス)を作成することです。

+0

これは、私たちの組織全体で使用されている共通のモデルクラスであるという問題があります。私は振舞いを変えずにこのクラスをJPAに移行する方法を探しています。あるいは、30の異なるチームがコードを調整するように強制しました。 – qualidafial

+0

これは、&at;列を使用してオプトインするのではなく、&at; Transientを使用してオプトアウトするJPAのスイッチに問題があることにも注意してください。この考えは、&at;列の注釈をどこにも必要とせずに、JPAを侵襲の少ないものにすることでした。これは私たちを苦しめ、この1つのクラスを従来のXML設定からJPAアノテーションに移行することを不可能にしました。 – qualidafial

+0

モデルを変更できない場合は、解決策が表示されません。 使用されていないAddressのプロパティを無視するだけで、DBに空白のままにしておく必要があります。汚い解決策が、最も侵襲的ではありません。 –

6

私の助言は、PartialAddress/NationalAddress/BillingAddressという新しいエンティティを作成することです。これはのみJPAマッピングのために使用され、顧客のインターフェースに露出していないことになります。

private PartialAddress billingAddress; 

public Address getBillingAddress() { 
    return billingAddress.toAddress(); 
} 

はそうでなければ、私はこの問題のため、多少醜い回避策が出ている、多分それは同様にあなたのために動作します。

@Embedded 
@AttributeOverrides({ 
    @AttributeOverride(name="address", [email protected](name="bill_addr"), 
    @AttributeOverride(name="city", [email protected](name="bill_city"), 
    @AttributeOverride(name="state", [email protected](name="bill_state"), 
    @AttributeOverride(name="zip", [email protected](name="bill_zip"), 
    @AttributeOverride(name="country", [email protected](name="bill_id + null"), 
}) 
Address billingAddress; 

私はOracleとのEclipseLinkを使用しています、同様にHibernate 3.6上で動作します:代わりに実際の列にフィールドをマッピングする、私はSQL NULLの定数を返します。そして、私は読み取り専用のオブジェクトに対してのみテストしました。理論的には、insertableと属性をfalseに設定するだけで十分です。

+2

これは非常に素晴らしく革新的な回避策です。私は直接無視されたプロパティをnullにマップします(つまり、 'column = @ Column(name =" null ")' –

+0

@KenChanの回避策はデータを永続させるためには許容されますが、データベースから読み込むときに問題があります。 "javax.persistence.PersistenceException:org.hibernate.exception.SQLGrammarException:ResultSetを抽出できませんでした"というメッセージが表示されます。 "ohejsSqlExceptionHelper - ERROR:列が見つかりませんtabl0_.null" –

関連する問題