Является ли плохой практикой использование DiscriminatorFormula для миграции баз данных Hibernate? - PullRequest
5 голосов
/ 02 августа 2010

У меня есть приложение, использующее Hibernate для сохранения данных, с Spring на вершине (для хорошей оценки). До недавнего времени в приложении был один постоянный класс: A:

@Entity
public class A {
  @Id
  @Column(unique = true, nullable = false, updatable = false)
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  public String name;
}

С тех пор я добавил подкласс A, который называется B:

@Entity
public class B extends A {
  public String description;
}

После добавления B я теперь не могу загрузить A. Было сгенерировано следующее исключение:

class org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException :: Object with id: 1 was not of the specified subclass: A (Discriminator: null); nested exception is org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: A (Discriminator: null)

Я добавил следующую аннотацию и свойство в B, и, похоже, это решило проблему. Это правильный способ решить проблему?

...
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'A' ELSE dtype END)")
public class A {
    private String dtype = this.getClass().getSimpleName();
    ...

1 Ответ

2 голосов
/ 03 августа 2010

(...) До недавнего времени в приложении был один постоянный класс, A:

со следующим представлением базы данных:

ID  NAME
--  ----
 1   foo
 2   bar

С тех пор я добавил подкласс A, называемый B (...)

И вы не указали аннотацию Inheritance, поэтому отображение SINGLE_TABLEстратегия используется.И В этой стратегии все классы в иерархии отображаются в одну таблицу.В таблице есть столбец, который служит «столбцом дискриминатора», то есть столбцом, значение которого идентифицирует конкретный подкласс, которому принадлежит экземпляр, представленный строкой.

Таблица затем стала:

ID  NAME DTYPE
--  ---- -----
 1   foo  NULL
 2   bar  NULL

Где DTYPE - имя столбца по умолчанию, которое будет использоваться для дискриминатора.

После добавления B я теперь не мог загружать A.Было сгенерировано следующее исключение (...)

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

Я добавил следующую аннотацию и свойство в B, и, похоже, это решило проблему.Это правильный способ решения проблемы?

Это один из способов, но он навязчив (ваши сущности не должны знать о столбце dtype) и специфичен для Hibernate.Другими словами, это взломать.

Для меня «правильный» способ решить эту проблему - обновить столбец DTYPE существующих записей A, чтобы установить значение 'A' (в Hibernate значением по умолчанию является имя объекта):

UPDATE A SET DTYPE='A' WHERE DTYPE=NULL

Таким образом, Hibernate сможет загрузить их правильно.

...