#java #hibernate #jpa
#java #переход в спящий режим #jpa
Вопрос:
Я пытаюсь реализовать очень простую модель наследования в Hibernate. В принципе, у меня есть один суперкласс, который можно вызвать A
, и несколько подклассов, все из которых наследуются от A
. Поскольку поведение, которое я вижу, одинаково для всех из них, на них можно просто ссылаться как B
.
То, к чему я пытаюсь прийти, это то, что описано здесь в разделе 6.2. В принципе, должна быть таблица для A
, которая содержит его поля, и таблица для B
, которая содержит только поля, отличные от подкласса, плюс столбец объединения обратно в таблицу для A
. Я использую автоматическую генерацию схемы Hibernate (включена только для модуля сохранения разработки).
Однако, когда я смотрю на схему, я вижу таблицу для A
, которая содержит ее поля (правильно), и таблицу для B
, которая содержит все поля в A
(неправильно), плюс поля, добавленные в B
. Мои классы аннотируются следующим образом:
@Entity
@Table(name="A")
@Inheritance(strategy = InheritanceType.JOINED)
public class A implements Serializable {
protected long id;
protected Date createDate;
protected String title;
protected boolean hidden;
public A() {
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
public Date getCreateDate() {
return createDate;
}
@Column(nullable = false)
public boolean isHidden() {
return hidden;
}
@Column(nullable = false)
public String getTitle() {
return title;
}
//also setters...
}
@Entity
@Table(name="B")
@PrimaryKeyJoinColumn(name="aId", referencedColumnName="id")
public class B extends A {
private String extraField;
public B() {
super();
}
@Column
public String getExtraField() {
return extraField;
}
//also setter...
}
Есть идеи, что я сделал не так? В частности, то, что я хочу видеть при просмотре сгенерированной схемы БД, выглядит примерно так:
Table A: {id, createDate, title, hidden}
Table B: {aId, extraField}
… и вместо этого я получаю:
Table A: {id, createDate, title, hidden}
Table B: {id, createDate, title, hidden, extraField}
Это просто невозможно с помощью автоматической генерации схемы Hibernate, или я где-то перепутал аннотации?
Ответ №1:
Ваша аннотация верна, она должна создать схему таблицы, которую вы хотите.
Но теперь вы получаете нежелательную схему, которая в точности соответствует схеме, созданной с использованием Table per concrete class
стратегии (т. е. @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
). Итак, я думаю, что одна из возможных причин заключается в том, что hibernate.hbm2ddl.auto
свойство в вашей конфигурации использует значение по умолчанию, которое является update
.
Поведение update
значения является :
-
Hibernate попытается создать сценарий обновления, чтобы обновить схему базы данных до текущего сопоставления при
SessionFactory
создании. -
Если оператор update не может быть выполнен, он будет пропущен (например, добавление столбца not null в таблицу с существующими данными)
-
Режим гибернации не удалит никаких данных во время обновления.(Например, если имя столбца изменено, он просто добавляет новый столбец с новым именем, но при этом сохраняет столбец с исходным именем)
Итак, я думаю, вы должны использовать @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
для генерации схемы ранее, которая создала следующую схему . Таблица A и таблица B не имеют никаких ассоциаций внешнего ключа друг с другом.
Table A: {id, createDate, title, hidden}
Table B: {id, createDate, title, hidden, extraField}
После этого вы изменили режим использования @Inheritance(strategy = InheritanceType.JOINED)
. В процессе обновления схемы hibernate просто обновил вашу схему, добавив ассоциацию внешнего ключа между TableA.id
и TableB.id
. Он сохранил все остальные столбцы в таблице B. Вот почему вы получаете текущую схему, даже если ваша аннотация верна.
Желаемая схема таблицы должна быть сгенерирована после удаления таблиц A и B из базы данных перед запуском программы гибернации . В качестве альтернативы вы можете установить hibernate.hbm2ddl.auto
значение create
, тогда hibernate удалит все таблицы перед созданием схемы таблицы .
Комментарии:
1. Спасибо, я не думаю, что я когда-либо использовал
InheritanceType.TABLE_PER_CLASS
, но в любом случае удаление таблиц и разрешение Hibernate регенерировать схему, как вы предложили, исправили ситуацию.