我们的系统中有一个存储资源键/值对的表。存储该值的列有两列; VARCHAR列表示较小的值,CLOB表示较大的值。在Java方面,它们被实例化为两个类之一,StandardResourceBundleValue或LargeResourceBundleValue,并且鉴别器列用于在一个表中区分它们:
<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>
当我尝试构建表时,出现以下错误:
实体映射中的重复列: com.foo.resourcebundle.LargeResourceBundleValue列: RESOURCE_TYPE(应使用insert =“false”update =“false”映射)
显然它不明白我想要做什么,但是应该有一种方法可行。那么如何将一个鉴别器字段公开为一个属性呢?
感谢。
答案 0 :(得分:2)
你做不到。对象具有类型,并且无法从一种类型切换到另一种类型。这就是Java的工作原理。
我认为你不应该在这里有两种类型的实体。为什么不将鉴别器存储为基本枚举列,并根据此枚举的值在varchar或clob列中存储/获取属性的值。确保所有内容都透明地封装在对象中,即使对于呼叫者来说,一切都会更容易。枚举字段甚至不能公开。您可以使用它来实现getMessageValue()
(从适当的列中获取值),并根据新值的长度在调用setMessageValue()
时更改其值。