2012-01-11 16 views
2

リソースキーと値のペアを格納するテーブルがシステムにあります。値を格納する列は2つあります。小さい値の場合はVARCHAR列、大きい値の場合はCLOB。 Java側では、それらは二つのクラスの1、StandardResourceBundleValueまたはLargeResourceBundleValueにインスタンス化され、かつ識別カラムは、一つのテーブルにそれらを区別するために使用されます。hbmファイル内の識別子として識別子の列をプロパティとして公開

<discriminator type="string"> 
    <column name="RESOURCE_TYPE" length="20" index="XIE1CPD_RESOURCE_BUNDLE_L_V"/> 
</discriminator> 
... 
<subclass name="StandardResourceBundleValue" discriminator-value="STANDARD"> 
    <property name="messageValue" type="string" column="STD_MSG_VALUE" length="400"/> 
</subclass> 
<subclass name="LargeResourceBundleValue" discriminator-value="LARGE"> 
    <property name="messageValue" type="materialized_clob" column="LARGE_MSG_VALUE"/> 
</subclass> 

ここでは楽しい部分です:の値ならばキーが小さく始まり(StandardResourceBundleValueとして保持された)、値がVARCHARより大きい値に変更されると、StandardResourceBundleValueに変換する方法が必要になります。これが起こっているコードでは、StandardResourceBundleValueを削除してLargeResourceBundleValueを作成することはできません。これは、制約違反を引き起こしているためです。

その識別器列のプロパティを定義することで、そのオブジェクトの値を変更するメソッドを持つことができるので、CLOBに値を保存し直すと、値が保存されます。

<property name="resourceType" type="string"> 
    <column name="RESOURCE_TYPE"/> 
</property>  

私はテーブルを構築しようとすると、私は次のエラーを取得する:

Repeated column in mapping for entity: com.foo.resourcebundle.LargeResourceBundleValue column: RESOURCE_TYPE (should be mapped with insert="false" update="false")

明らかにそれは私がやろうとしているものを理解していないが、それは存在しなければならないことを意味しますそれを行う方法。では、どのように弁別子フィールドをプロパティとして公開しますか?

ありがとうございました。

答えて

2

これはできません。オブジェクトには型があり、ある型から別の型に切り替えることはできません。それがJavaの仕組みです。

ここでは2つのタイプのエンティティを使用しないでください。弁別器を基本列挙型列として格納し、この列挙型の値に基づいてvarcharまたはclob列にプロパティの値を格納またはフェッチするのはなぜでしょうか。すべてがオブジェクトに透過的にカプセル化されていることを確認してください。呼び出し元であってもすべてが簡単になります。 enumフィールドは公開することさえできませんでした。これを使用してgetMessageValue()(適切な列から値を取得)を実装し、新しい値の長さに基づいてsetMessageValue()が呼び出されたときにその値を変更します。

+0

これで終わるかもしれませんが、これら2つのクラスを使用するクラスは変更する必要があります。私はこれが、私たちがやろうとしているものよりはるかに洗練されたソリューションだが、はるかに侵略的だと同意する。これはすべて既存のコードなので、単なる別の方法で書くことではありません。 –

+0

1クラスにリファクタリングしました。疑惑を確認していただきありがとうございます。 –