Не вдається використати генерацію ключа ключа стовпця з <union-subclass> (TABLE_PER_CLASS)


96

com.something.SuperClass:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass implements Serializable {
    private static final long serialVersionUID = -695503064509648117L;

    long confirmationCode;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!!
    public long getConfirmationCode() {
        return confirmationCode;
    }

    public void setConfirmationCode(long confirmationCode) {
        this.confirmationCode = confirmationCode;
    }
}

com.something.SubClass:

@Entity
public abstract class Subclass extends SuperClass {
    private static final long serialVersionUID = 8623159397061057722L;

    String name;

    @Column(nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Дає мені цей виняток:

Caused by: org.hibernate.MappingException: Cannot use identity column key
generation with <union-subclass> mapping for: com.something.SuperClass

Який найкращий та найзручніший спосіб для мене створити посвідчення особи? Я не хочу змінювати свою стратегію успадкування.

Відповіді:


230

Проблема тут полягає в тому, що ви змішуєте спадщину "таблиця за класом" і GenerationType.Auto. Розглянемо стовпець ідентичності в MsSQL. Він базується на стовпцях. У стратегії "таблиця за класом" ви використовуєте по одній таблиці на клас, і кожна з них має ідентифікатор.

Спробуйте:

@GeneratedValue(strategy = GenerationType.TABLE)


2
Ідеальне рішення. Навіть форуми Hibernate, схоже, не мали цього рішення, і вони обходили
Весняна мавпа

1
Чи ця проблема стосується лише MySql або звичайної, оскільки я дивлюсь одне з відео для підходу до таблиці для кожного класу, і він працював нормально, оскільки використовувався postgres
Прашант,

1
Нещодавно я зіткнувся з цим під час тестування програми Dropwizard. У моєму випадку я звернувся до нього, переконавшись, що використовував ті самі параметри конфігурації, які використовував DW для створення фабрики сесій. Я майже впевнений, що встановило властивість "hibernate.id.new_generator_mappings" на true - це те, що це виправило. Це DW 0.7.0, Hibernate 4.3.1, DB був H2.
sfitts

1
Це чудово працює. Однак настійно рекомендується не віддавати перевагу використанню стратегії генерації ідентифікаторів "TABLE", оскільки вона ініціює безліч запитів (вибір, вставка та оновлення) та підтримує блокування для створення унікальних значень для первинного ключа. То що може бути альтернативним рішенням цього випадку, якщо у нас є якийсь великий сценарій успадкування? Це, безумовно, значною мірою вплине на ефективність.
MAC

8

Цікаво, чи це особлива проблема діалекту бази даних, оскільки, переглядаючи навчальний посібник YouTube з PostgreSQL як базовою базою даних, я побачив, що творець відео успішно запускає додаток із типовим @GeneratedValue. У моєму випадку (базовою базою даних є MySQL) мені довелося змінити стратегію @GeneratedValue на GenerationType.TABLE точно так, як пропонує zoidbeck.

Ось відео: https://www.youtube.com/watch?v=qIdM4KQOtH8


Postgres може робити успадкування, тому ви можете мати рацію, що це стосується бази даних: postgresql.org/docs/8.1/static/ddl-inherit.html Відео не пояснює (або я пропустив), як створюється схема. Тож, можливо, діалект NHibernate postgres здатний зробити це самостійно, або замість цього вам доведеться додати «СПАДКИ» вручну. Насправді я не можу сказати.
zoidbeck 20.03.13

6
У PostgreSQL за замовчуванням використовується Hibernate GenerationType.SEQUENCE. Тому там він працює автоматично. Це абсолютно нічого спільного з PostgreSQL INHERITS.
Хеннінг,

я користувався тим самим посібником, і використання @Generated викликало проблему, оскільки я використовую MySql. Витратив багато часу на налагодження, поки не побачив цю публікацію
Дін Джон

5

Погодьтеся з відповіддю zoidbeck. Вам потрібно змінити стратегію на:

@GeneratedValue(strategy = GenerationType.TABLE)

Але це ще не все, вам потрібно створити нову таблицю, яка міститиме послідовність первинного ключа таблиці вашої анотації. Змініть своє відображення на

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator")
@TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator")
public long getConfirmationCode() {
   return confirmationCode;
}

І нова таблиця в базі даних повинна виглядати наступним чином: введіть тут опис зображення

Коли ви запустили програму, Hibernate вставить рядок, де sequence_nameбуде вказано ім'я сутності ( SuperClassу цьому прикладі), і sequence_next_hi_valueзначення буде автоматично збільшено та використане для нових записів усіх таблиць реалізації підкласів.


2

У нашому випадку ми використовуємо базу даних PostreSQL для розробки та виробництва та базу даних hsqldb в пам'яті для тестів. В обох випадках ми використовуємо послідовність для створення ідентифікатора. Мабуть, GenerationType.AUTOза замовчуванням встановлено SEQUENCEдля postgres, але не вдалося виконати наші локальні тести (для hsqldb має бути встановлено щось інше).

Тому рішення, яке працювало для нас, явно використовуємо GenerationType.SEQUENCE.



0

Існує відповідність стандартам SQL між MySQL та PostgreSQL. PostgreSQL Postgres розуміє хорошу підмножину SQL92 / 99 плюс деякі об'єктно-орієнтовані функції цих підмножин. Postgres здатний обробляти складні підпрограми та правила як декларативні запити SQL, підзапити, подання, підтримку для багатьох користувачів, транзакції, оптимізацію запитів, успадкування та масиви. Не підтримує вибір даних у різних базах даних.

MySQL MySQL використовує SQL92 як свою основу. Працює на незліченних платформах. Mysql може створювати запити, які можуть об’єднувати таблиці з різних баз даних. Підтримує як ліве, так і праве зовнішнє з'єднання, використовуючи як синтаксис ANSI, так і ODBC. Починаючи з MySQL 4.1, починаючи з цього випуску, MySQL буде обробляти підзапити. Перегляди підтримуються станом на випуск 5.

Для детального опису відвідайте. http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html


Будь ласка, не почувайся погано з цього приводу, але я вважаю, що порівняння MySQL та PostgreSQL не має відношення до теми (хоча за замовчуванням Hibernate за замовчуванням для них різні).
mrts
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.