JPA / Hibernate - InheritanceType.JOINED ведет себя как InheritanceType.TABLE_PER_CLASS - PullRequest
4 голосов
/ 17 мая 2011

Я пытаюсь реализовать очень простую модель наследования в 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 Ответ

4 голосов
/ 17 мая 2011

Ваша аннотация правильная, она должна создать схему таблицы, которую вы хотите.

Но теперь вы получаете нежелательную схему, которая является именно схемой, созданной с использованием стратегии Table per concrete class (то есть @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)).Итак, я думаю, что одной из возможных причин является то, что свойство hibernate.hbm2ddl.auto в вашей конфигурации использует значение по умолчанию, равное update.

Поведение значения update:

  • Hibernate попытается создать скрипт обновления для обновления схемы базы данных до текущего сопоставления, когда SessionFactory

  • Если оператор обновления не может быть выполнен, он будет пропущен (например, добавление ненулевого столбца в таблицу с существующими данными)

  • Hibernate не будет удалять какие-либо данные во время обновления (например, если имя столбца изменяется, он просто добавляет новый столбец с новым именем, но при этом сохраняет столбец с исходным именем)

Итак, я думаю, вы должны использовать @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 удалит все таблицы перед генерацией схемы таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...