@GeneratedValue полиморфный абстрактный суперclass над MySQL

В приложении Spring MVC с использованием Hibernate и MySQL у меня есть абстрактный суперclass BaseEntity который управляет значениями идентификаторов для всех других объектов в модели. В поле id используется @GeneratedValue . Я сталкиваюсь с проблемой, когда мой код пытается сохранить любой из подclassов, расширяющих BaseEntity . Проблема связана с выбором GenerationType для @GeneratedValue .

В каждом месте моего кода, где подclass BaseEntity пытается сохранить базу данных MySQL, я получаю следующую ошибку:

 ERROR SqlExceptionHelper - Table 'docbd.hibernate_sequences' doesn't exist 

Я прочитал много сообщений об этом на SO и в google, но они либо касаются других баз данных (а не MySQL), либо они не занимаются абстрактными суперclassами. Я не могу решить проблему, используя GenerationType.IDENTITY потому что я использую абстрактный суперclass для управления полями для всех объектов в модели. Точно так же я не могу использовать GenerationType.SEQUENCE потому что MySQL не поддерживает последовательности.

Итак, как я могу решить эту проблему?

Вот код для BaseEntity.java :

 @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class BaseEntity { @Id @GeneratedValue(strategy = GenerationType.TABLE) protected Integer id; public void setId(Integer id) {this.id = id;} public Integer getId() {return id;} public boolean isNew() {return (this.id == null);} } 

Ниже приведен пример кода для одного из объектов, который расширяет BaseEntity :

 @Entity @Table(name = "ccd") public class CCD extends BaseEntity{ //other stuff } 

Вот DDL:

 CREATE TABLE IF NOT EXISTS ccd( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, #other stuff )engine=InnoDB;SHOW WARNINGS; 

Вот код JPQL в DAO:

  @Override @Transactional public void saveCCD(CCD ccd) { if (ccd.getId() == null) { System.out.println("[[[[[[[[[[[[ about to persist CCD ]]]]]]]]]]]]]]]]]]]]"); this.em.persist(ccd); this.em.flush(); } else { System.out.println("]]]]]]]]]]]]]]]]]] about to merge CCD [[[[[[[[[[[[[[[[[[[[["); this.em.merge(ccd); this.em.flush(); } } 

РЕДАКТИРОВАТЬ:

Причина, по которой я не могу использовать @MappedSuperClass в этой ситуации, заключается в том, что мне нужно иметь отношения ManyToOne которые допускают использование нескольких подтипов взаимозаменяемо. Посмотрите AccessLog class AccessLog . У этого есть actor_entity и target_entity . Могут существовать многие типы объектов субъекта и многие типы целевых объектов, но все они наследуются от BaseEntity . Это наследование позволяет базе данных данных accesslogs в MySQL иметь только одно поле actor_entity_id и только одно поле target_entity_id вместо того, чтобы иметь по несколько полей для каждого. Когда я изменяю @Entity выше BaseEntity на @MappedSuperClass , возникает другая ошибка, указывающая, что AccessLog не может найти BaseEntity . BaseEntity нуждается в annotations AccessLog чтобы AccessLog имел полиморфные свойства.

 @Entity @Table(name = "accesslogs") public class AccessLog extends BaseEntity{ @ManyToOne @JoinColumn(name = "actorentity_id") private BaseEntity actor_entity; @ManyToOne @JoinColumn(name = "targetentity_id") private BaseEntity target_entity; @Column(name="action_code") private String action; //getters, setters, & other stuff } 

ВТОРОЙ РЕДАКТИРОВАНИЕ:

Согласно предложению JBNizet, я создал таблицу hibernate_sequences следующим образом:

 CREATE TABLE IF NOT EXISTS hibernate_sequences( sequence_next_hi_value int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY )engine=InnoDB;SHOW WARNINGS; 

Но теперь я получаю следующую ошибку:

 Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sequence_name' in 'where clause' 

Здесь находится hibernate sql, вызывающий ошибку, а затем следующие две строки трассировки стека:

 Hibernate: select sequence_next_hi_value from hibernate_sequences where sequence_name = 'BaseEntity' for update ERROR MultipleHiLoPerTableGenerator - HHH000351: Could not read or init a hi value com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sequence_name' in 'where clause' 

Как это разрешить?

Поскольку вы используете генератор идентификаторов TABLE, вам нужно создать эту таблицу. Если вы не используете генераторы расширенных идентификаторов , скорее всего, вы собираетесь использовать MultipleHiLoPerTableGenerator .

MultipleHiLoPerTableGenerator может использовать одну таблицу для всех генераторов идентификаторов таблиц.

Мое предложение – захватить таблицу ddl из ваших интеграционных тестов, если вы используете hbmddl для построения схемы тестирования. Если вы используете пролетный или жидкостной код для тестирования, вы можете добавить плагин maven для создания схемы ddl.

После того, как у вас есть схема, вам нужно взять точную команду create table и добавить ее в свою базу данных MySQL.

Какой беспорядок … AUTO_INCREMENT – скрытая последовательность MySQL. Радикальная проблема заключается в том, что MySQL не может одновременно вставлять и возвращать ПК, но для Hibernate это необходимо, а INSERT – для нового Entity.

Проблемы, с которыми вы сталкиваетесь:

  1. Если Hibernate сохранит новый Entity, он попытается immerdentelly установить id на новый EntityBean. Поэтому hibernate должен прочитать, какой идентификатор будет использоваться базой данных до спящего режима, чтобы сохранить новый Tuple в таблице.
  2. Если у вас есть несколько Серверов, которые обращаются к базе данных, вы должны разрешить сессионному заводу hibernate использовать встроенную последовательность (AUTO-INCREMENT) или позволить hibernate решить ( GenerationType.AUTO / GenerationType.IDENTITY ), насколько большой открытый диапазон зарезервированных PK – это (работа DB-Architect). (У нас около 20 серверов для одной базы данных, поэтому на хорошо используемой таблице мы используем PK-расстояние +100). Если только один сервер имеет доступ к базе данных GenerationType.TABLE должен быть правильным.

Спящий режим должен вычислять следующий id самостоятельно, используя max(*)+1 но:

  • Что делать, если два запроса запрашивают max(*)+1 одновременно / с тем же результатом? Справа: последняя попытка insert не удастся.

Таким образом, вам нужно иметь таблицу LAST_IDS в базе данных, которая хранит последние таблицы PK. Если вы хотите добавить его, вы должны сделать следующие шаги:

  1. Начать оптимизацию чтения.
  2. SELECT MAX (address_id) FROM LAST_IDS
  3. хранить максимум в переменной java, т.е.: $ OldID.
  4. $ NewID = $ OldID + 1. (+100 в пессимистическом блокировке)
  5. UPDATE LAST_IDS SET address_id = $newID WHERE address_id = $oldID ?
  6. совершить транзакцию с оптимизацией чтения.
  7. если фиксация прошла успешно, сохраните $newID setID() для setID() в HibernateBean, который вы хотите сохранить.
  8. Наконец, пусть Hibernate вызывает вставку.

Это единственный способ узнать.

BTW: Hibernate-Entitys должны использовать наследование только в том случае, если наследование базы данных поддерживается на основе таблиц типа PostgreSQL или Oracle .

  • Индекс MySQL Integer vs DateTime
  • использовать переменную для имени таблицы в mysql sproc
  • Использует ли MySQL foreign_key_checks всю базу данных?
  • Как реализовать одиночное наследование таблиц с помощью Larvel's Eloquent?
  • Суммируйте результаты нескольких запросов, а затем найдите 5 лучших в SQL
  • Вставить и вставить MySQL
  • mysqli_stmt :: bind_param (): Число элементов в строке определения типа не совпадает с числом переменных привязки
  • Ошибка MySQL 1093 - Невозможно указать целевую таблицу для обновления в предложении FROM
  • Как сжать / очистить файл ibdata1 в MySQL
  • Как подключиться к базе данных MySQL?
  • MySQL FULL JOIN?
  • Interesting Posts

    Как получить имя цвета при наличии значения RGB в C #?

    Запустить операционную систему с двойной загрузкой

    Google Chrome обнаружен как PWS: Win32 / Zbot от MSE

    Есть ли способ полностью удалить Chrome OS на chromebook – и установить Linux (не с двойной загрузкой)

    Как заблокировать веб-сайты в Windows 8 без дополнительного программного обеспечения?

    Каталог проекта Visual Studio 2015 Database Project содержит файл с расширением jfm

    Что случилось с диском B: в Windows и почему жесткий диск по умолчанию для C?

    Как я могу переадресовать домен в свой ящик дома?

    Ближайшая точка на кубической кривой Безье?

    определить размер массива, если он передан функции

    Как добавить несколько компонентов в JFrame?

    NoAutoRebootWithLoggedOnUsers все еще поддерживается / эффективен в Windows 10?

    Android Retrofit – onProgressUpdate для показа уведомления о ходе работы

    Каков наилучший способ установить регистр в ноль в сборке x86: xor, mov или или?

    Странная вставка из Vim по щелчку мыши

    Давайте будем гением компьютера.