Условное сопоставление в Hibernate 3.0?

Как создать сопоставление в спящем режиме, которое зависит от свойства типа, вставлять/извлекать данные в/из соответствующего столбца.

Структура:

СТОЛБЦЫ ТАБЛИЦЫ:

|TYPE | CHARACTER | DATE | TIME | NUMERIC|

ПОЖО:

class Pojo {

 private int type;
 private Object data;

 ...

}

Примеры:

  • Insert/Update
    Если тип равен 1, мы вводим значение в столбец CHARACTER.

  • Select
    Если тип равен 2, мы получаем значение из столбца NUMERIC.

СОВЕТ: Структура, в которой у нас есть два столбца, и мы ОБЪЕДИНЯЕМ результат, не подходит для этого случая.


person Damian Leszczyński - Vash    schedule 06.07.2010    source источник


Ответы (2)


Решение, которое я выбрал для этого, - это таблица для сопоставления иерархии классов с целочисленным дискриминатором.

Я создал базовый абстрактный универсальный класс, в котором хранится объект

 public abstract class ValueBase<T> {

   private Long id; 
   private int valueType;
   private T value;

   public T getValue(){
     return value;
   }

   public void setValue(T value){
     this.value = value;
   }

   protected void setValueType(int valueType) {
      this.valueType = valueType;
   }

   public int getValueType(){
     return this.valueType;
   }

   private void setID(Long id) {
      this.id = id;
   }

   public int getID(){
     return this.id;
   }


 }

Для управления типами я создал и интерфейс, но есть возможность перечисления с использованием инкапсуляции, представленной Артуром.

public interface IValueTypes() {

 public static final int NONE = -1;
 public static final int NUMERIC = 0;
 public static final int CHARACTER = 1;
 public static final int DATE = 2;
 public static final int TIME = 3;
 public static final int BOOLEAN = 4;

}

Для каждого типа я создал класс

 public class NumericType extedns ValueBase<BigDecinal> {

    public NumericType(){
      super();
      setValueType(IValueTypes.NUMERIC);
    }

 }

 public class CharacterType extedns ValueBase<String> {

    public NumericType(){
      super();
      setValueType(IValueTypes.CHARACTER);
    }

 }

СОВЕТ: Чтобы разрешить использование числа в качестве значения дискриминатора, нам нужно сначала указать его для класса, который мы сопоставляем, потому что по умолчанию используется имя класса [String], и если мы попытаемся использовать числовой дискриминатор для сопоставления подкласса, мы получим ошибка гибернации говорит о несоответствии типов.

<class name="TestValue" table="TestValues" schema="TEST" abstract="true" discriminator-value="-1"> 
  <id name="id" type="java.lang.Long">
    <column name="VALUE_ID" precision="22" scale="0" />
    <generator class="native"/>
  </id>

  <discriminator column="TYPE_VALUE" not-null="false" type="integer"/> 

  <subclass discriminator-value="0" name="NumericType">
    <property name="value" type="java.math.BigDecimal" column="NUMERIC" not-null="false"/>
  </subclass>   

  <subclass discriminator-value="1" name="CharacterType">
    <property name="value" type="java.lang.String" column="CHARACTER" not-null="false"/>
  </subclass>   

</class>

Хотя мы извлекаем объект из базы данных, он всегда находится в заданном типизированном классе, с которым мы можем легко работать, и мы используем одно место для их сохранения, сохраняя базовый класс.

person Damian Leszczyński - Vash    schedule 16.08.2010
comment
Спасибо за предоставленное решение (+1) - person Arthur Ronald; 16.08.2010

Такое поведение достигается с помощью инкапсуляции. Например, у меня есть столбец String (Y/N) в базе данных (INSERT/UPDATE), который инкапсулирован логическим значением (SELECT) следующим образом.

public class SomeEntity {

    private boolean checked;

    private boolean isChecked() {
        return this.checked;
    }

    public void setChecked(boolean checked) {
        this.checked = checked;
    }

    public String getCheckedAsString() {
        return checked ? "Y" : "N";
    }

    public void setCheckedAsString(String checked) {
        this.checked = checked.equals("Y") ? true : false;
    }

}

Ваше сопоставление идет сюда

<property name="checkedAsString" type="string" column="CHECKED"/>

Эта стратегия объясняется здесь, которую я использовал помимо конверсии, в качестве обходного пути. Чтобы разрешить использование ключевых слов String Java в качестве Enum. См. здесь

person Arthur Ronald    schedule 14.08.2010
comment
Закрыть, но это не полностью решает мою проблему. В качестве решения я выбрал таблицу для сопоставления иерархии классов с целочисленным дискриминатором. Это некоторая расширенная версия инкапсуляции. - person Damian Leszczyński - Vash; 16.08.2010