Спящий режим 4: сохраняющиеся значения столбца дискриминатора InheritanceType.JOINED

У меня есть простая СОЕДИНЕННАЯ иерархия документов:

CREATE TABLE Documents
(
  id INTEGER NOT NULL,
  discriminator ENUM('official','individual','external') NOT NULL,
  file_name VARCHAR(200) NOT NULL,
  PRIMARY KEY (id)
);

CREATE SystemDocuments
(
  id INTEGER NOT NULL,
  binary_data BLOB NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (id) REFERENCES Documents (id)
);

CREATE ExternalDocuments
(
  id INTEGER NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (id) REFERENCES SystemDocuments (id)
);

Как вы можете видеть, все подтаблицы имеют один и тот же идентификатор из таблицы «Документы». Кроме этого SystemDocuments добавляет столбец binary_data, а ExternalDocuments не добавляет новых свойств. (Также обратите внимание, что в иерархии есть две другие конкретные подтаблицы, обозначенные 'official' и 'individual', которые здесь не имеют значения.)

Вот сопоставления для приведенных выше таблиц:

Документ.java:

@Entity
@Table(name = "Documents")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
//@DiscriminatorOptions(force = true) // <-- Hibernate 4-specific annotation not inserting discriminator values
public abstract class Document implements Serializable
{
    @Id
    @Column
    protected Integer id;

    @Column(name = "file_name")
    protected String fileName;

    ...
}

SystemDocument.java:

@Entity
@Table(name = "SystemDocuments")
public abstract class SystemDocument extends Document
{
    @Lob
    @Column(name = "binary_data")
    protected byte[] binaryData;

    ...
}

ExternalDocument.java:

@Entity
@Table(name = "ExternalDocuments")
@DiscriminatorValue(value = "external")
public class ExternalDocument extends SystemDocument
{
    ...
}

Последний класс должен быть сопоставлен со значением столбца дискриминатора документов 'external'. При поиске сущностей через EntityManager.find дискриминаторы возвращаются правильно, на самом деле потому, что дискриминаторы моих тестовых данных были правильно ВСТАВЛЕНЫ в БД.

Теперь я использую следующий код для вставки новых документов/файлов в систему через JPA и загрузчик файлов:

...

UploadedFile uf = event.getUploadedFile();

// set ID, file name, and binary data
ExternalDocument detachedExternalDocument =
    new ExternalDocument(1234567, uf.getName(), uf.getData());

docService.create(detachedExternalDocument);

Однако при проверке БД я вижу, что Hibernate не вставляет значение дискриминатора 'external' в столбец discriminator таблицы Documents.

В прошлом были проблемы с этим, см. https://hibernate.onjira.com/browse/ANN-140 и совсем недавно для Hibernate 4 https://hibernate.onjira.com/browse/HHH-4358, так что, скорее всего, так и должно быть.

Затем я нашел http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.html в текущих документах API Hibernate 4, но это не работает (см. @DiscriminatorOptions в классе Document).

Как я могу заставить Hibernate 4 вставлять дискриминаторы используя необработанные аннотации?

Примечание. Я не хочу отображать столбец дискриминатора как обычный столбец.


person Kawu    schedule 02.11.2011    source источник


Ответы (1)


Прежде всего, этот вопрос является дубликатом Discriminator in InheritanceType.JOINED.

Похоже, что сохранение значений дискриминатора в наследовании JOINED не требуется спецификацией JPA. Вот что я получил по электронной почте от члена группы экспертов JPA:

Спецификация не требует, чтобы реализация использовала столбцы дискриминатора для реализации JOINED наследования, однако предполагается, что если указан @DiscriminatorColumn, то он будет использоваться, т. е. значения будут записаны. Мы не указываем явно, что если @DiscriminatorColumn указан в коде, он должен использоваться, точно так же, как мы не указываем явно, что если указаны @Column или @JoinColumn, значения должны храниться в таблице, но есть только то, что мы можем или должны указать. На самом низком уровне просто предполагаются определенные законы физики и разума.

Эта проблема уже давно связана с Hibernate, см. здесь:

https://hibernate.atlassian.net/browse/ANN-140

Комментарий отказа:

EJB3 НЕ требует использования дискриминаторов со стратегиями отображения JOINED. Это разрешено для низших реализаций стратегии сопоставления JOINED, для которых требуется дискриминатор. Hibernate не нуждается в дискриминаторе, потому что Hibernate лучше этих других низших реализаций.

В конце концов, только для стратегии SINGLE_TABLE требуется столбец дискриминатора, JOINED может быть реализован без него. Проблема с Hibernate в настоящее время заключается в том, что он вызывает несогласованность данных при сохранении подобъектов в наследовании JOINED, сопоставленном с @DiscriminatorColumn, даже несмотря на то, что спецификация JPA рекомендует сохранять значения дискриминатора, если дискриминатор используется с JOINED. Смотрите больше на RFE здесь:

https://hibernate.atlassian.net/browse/HHH-6911

person Kawu    schedule 20.12.2011
comment
Недавно к этой заявке (HHH-6911) были добавлены дополнительные комментарии. Кажется, теперь Hibernate (4.2.9, 4.3.X) больше не игнорирует столбец дискриминатора, когда он явно указан в коде. - person Andy; 22.12.2013