Сценарий 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... и так далее.