Spring JPA композитный ПК с одним автоинкрементом - PullRequest
2 голосов
/ 27 мая 2019

Я пытаюсь сохранить сущность с составным первичным ключом, один из которых должен быть автоматически увеличен, используя Spring Boot 2.1.2.RELEASE + JPA (используя стартеры) и MySQL (InnoDB).У меня есть абстрактный класс с 2 неабстрактными подклассами, и я использую стратегию единой таблицы для наследования.

Я искал, как это сделать, но каждый пост, который, кажется, ищетто же самое, что и я, заканчивается без ответа ( пример ).

Моя текущая настройка выглядит так (сеттеры, геттеры и конструкторы опущены для ясности).

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@IdClass(MyEntityPK.class)
public abstract class MyEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    long pk1; //Should be auto-incremented

    @Id
    OffsetDateTime pk2;

    //More fields...
public class MyEntityPK implements Serializable {
   private static final long serialVersionUID = 1L;

   long pk1;
   OffsetDateTime pk2;
}
@Repository
public interface MyEntityRepository extends CrudRepository<MyEntity, MyEntityPK> {
   //Some methods like save().
}


Первая проблема, которую я обнаружил, была с генерацией таблицы.MySQL позволяет создавать PK, если он объявлен как

PRIMARY KEY (pk1, pk2)

, но не в другом порядке

PRIMARY KEY (pk2, pk1)

При создании таблицы Hibernate использует вторую, что приводит к сбою.Также пытался изменить порядок полей, но безрезультатно.Я думаю, что это может быть проблемой с Hibernate, но я не уверен.Кто-нибудь может подтвердить?Во всяком случае, я решил это, создав сценарий DDL вручную и отключив автоматический DDL с помощью Hibernate.

Следующая проблема, для которой я не нашел ответа, заключалась в том, что сущности были правильно сохранены в таблице, ноid, возвращаемый методом сохранения репозитория, всегда был 0. Я вручную устанавливал pk2 перед сохранением, оставляя pk1 для завершения БД.

entity.setPk2(OffsetDateTime.now());
Entity savedEntity = repository.save(entity); //savedEntity has id 1 in table but 0 in code

Во время отладки я пришел к этому Метод isNew () .Оказывается, он возвращал false, потому что MyEntityPK отличался от null (я установил pk2).Это, конечно, не то, что я ожидал, так как я на самом деле сохраняю новую сущность, учитывая, что мой PK составной, и я оставил одно поле пустым.Итак, я также думаю, что это может быть ошибкой.Некоторые классы переопределяют метод isNew (), но кажется, что они не используются.

Я что-то не так делаю или это ошибка?Помощь оценена :) 1027 *

1 Ответ

0 голосов
/ 28 мая 2019

@ GeneratedValue (стратегии = GenerationType.IDENTITY) для @EmbededId или @IdClass не поддерживается.

Вот ошибка, относящаяся именно к вашему запросу, которая была отклонена hibernate https://hibernate.atlassian.net/browse/ANN-268

Вот еще одна гораздо более поздняя ошибка, сообщающая об этом.Заметьте здесь комментарий Влада Михалча:

Это не блокиратор, а просто серьезная проблема. Например, спецификация JPA даже не говорит, разрешены ли сгенерированные идентификаторы в составном идентификаторе.

В любом случае, это работает только как @IdClass с идентификаторами на основе последовательности, как объясняется в этомarticle.

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

В статье в цитате объясняется, как отобразить @GeneratedValue (стратегии = GenerationType.SEQUENCE) на композитный.

...