Expor uma coluna discriminadora como uma propriedade no arquivo hbm
-
27-10-2019 - |
Pergunta
Temos uma tabela em nosso sistema que pares de chave de recurso lojas / valor. Há duas colunas para armazenar o valor; uma coluna VARCHAR para valores menores e um CLOB para valores maiores. No lado do Java, que são instanciado em uma das duas classes, uma StandardResourceBundleValue ou um LargeResourceBundleValue, e uma coluna discriminadora é usado para distingui-los na tabela de um:
<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>
Aqui está a parte divertida: Se o valor de uma chave começou pequeno (e persistiu como um StandardResourceBundleValue), então o valor é alterado para um maior que o VARCHAR, precisamos de uma maneira para convertê-lo a um StandardResourceBundleValue. O código que isso está acontecendo em não pode simplesmente excluir o StandardResourceBundleValue e criar um LargeResourceBundleValue, porque é isso que causa violações de restrição.
O que gostaríamos de fazer é definir uma propriedade para essa coluna discriminador, de modo a classe base pode ter um método que as mudanças que o valor no objeto, de modo que quando é persistiu novamente ele vai salvar o valor no CLOB.
<property name="resourceType" type="string">
<column name="RESOURCE_TYPE"/>
</property>
Quando eu tentar construir a tabela, eu recebo o seguinte erro:
repetida coluna no mapeamento de entidade: coluna com.foo.resourcebundle.LargeResourceBundleValue: RESOURCE_TYPE (devem ser mapeados com a inserção = "false" update = "false")
É claro que não entende o que eu estou tentando fazer, mas faz sentido que deve haver uma maneira de fazê-lo. Assim como você expor um campo discriminador como uma propriedade?
Graças.
Solução
Você não pode fazer isso. Um objeto tem um tipo, e não pode mudar de um tipo para outro. Isso é apenas como Java funciona.
Eu acho que você simplesmente não deve ter dois tipos de entidades aqui. Por que você não apenas armazenar o discriminador como uma coluna básica enum, e armazenar / buscar o valor da propriedade na coluna varchar ou clob com base no valor desta enumeração. Certifique-se de tudo é transparente encapsulado no objeto, e tudo será mais fácil, mesmo para os chamadores. O campo enum pode até não ser tornada pública. Você usá-lo para implementar getMessageValue()
(obter o valor da coluna for o caso), e você alterar seu valor quando setMessageValue()
é chamado, com base no comprimento do novo valor.