Сценарий Spring изменил способ автоинкремента идентификаторов через @GeneratedValue?

Spring-Boot 2.0.0, похоже, изменил способ автоматической настройки Hibernate.

Пусть предположим две простые и независимые сущности JPA:

@Entity
class Car {
   @Id
   @GeneratedValue
   private long id;
   //....
} 

@Entity
class Airplane {
   @Id
   @GeneratedValue
   private long id;
   //....
}

Ранее, используя Spring-Boot 1.5.10, я смог генерировать отдельные последовательности автоматических приращений, что означает, что я могу получить Car с 1 в качестве первичного ключа и Airplane с 1 в качестве первичного ключа. Никакой корреляции между ними, например, нет общей последовательности.

Теперь, с 2.0.0, когда я последовательно создаю очень первый Car затем самый первый Airplane, автомобиль получает 1 как id, а самолет получает 2.

Похоже, что он должен иметь дело с GeneratedType.AUTO, то есть "используется по умолчанию", указанным в @GeneratedValue аннотации @GeneratedValue.
Однако мои рассуждения, кажется, останавливаются здесь, поскольку GeneratedType.AUTO также был установлен по умолчанию с 1.5.10.

Простым обходным решением, чтобы оправдать мои ожидания, является указание типа стратегии IDENTITY для генерации следующим образом:

@Entity
class Car {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private long id;
   //....
} 

@Entity
class Airplane {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private long id;
   //....
}

Я не могу понять объяснения этого поведения.

Что изменило Spring-boot 2.0.0, объяснив этот сценарий?

Ответы

Ответ 1

Spring Boot 2.0 использует Hibernate 5.2 (https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes).
Спящий режим изменяет свою GeneratedType.AUTO с 5.2. Любая база данных, которая не поддерживает последовательности изначально (например, MySQL), они используют генератор TABLE вместо IDENTITY. (https://hibernate.atlassian.net/browse/HHH-11014)

Вот почему GeneratedType.AUTO не работает так, как вы ожидали.

Ответ 2

Если вам нужно быстрое решение, не ориентированное на будущее, чтобы предотвратить возникновение этой проблемы:

spring.jpa.hibernate.use-new-id-generator-mappings=false, начиная с документов Spring Boot 2:

spring.jpa.hibernate.use-new-id-generator-mappings= # Whether to use Hibernate newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.

Это предотвратит использование новых генераторов и сохранит старые функции, включенные в Spring boot 1.x.x.

Обратите внимание, что это, вероятно, не лучшее решение, но оно очень полезно в краткосрочной перспективе.

Ответ 3

Как отметил Эндрю в комментарии, если вы не хотите, чтобы идентификатор увеличивался при создании значений в других таблицах, вы можете указать свой идентификатор следующим образом:

@Id
@GeneratedValue(
    strategy= GenerationType.AUTO,
    generator="native"
)
@GenericGenerator(
    name = "native",
    strategy = "native"
)
private Long id;

При этом у каждой таблицы будет уникальный идентификатор, начиная с 1,2,3... и так далее.