web-dev-qa-db-fra.com

Spring-boot a-t-il changé la façon dont l'incrémentation automatique des identifiants fonctionne via @GeneratedValue?

Spring-Boot 2.0. semble avoir modifié la façon dont Hibernate est configuré automatiquement.

Supposons deux entités JPA simples et indépendantes:

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

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

Auparavant, en utilisant Spring-Boot 1.5.1, je pouvais générer des séquences distinctes d'auto-incréments, ce qui signifie que je peux obtenir un Car avec 1 comme clé primaire et un Airplane avec 1 comme clé primaire aussi. Aucune corrélation entre eux, par exemple aucune séquence partagée.

Maintenant, avec 2.0., quand je crée séquentiellement un tout premier Car puis un tout premier Airplane, la voiture obtient 1 comme id et avion obtient 2.

Il semble qu'il doive faire face aux GeneratedType.AUTO, c'est-à-dire "utilisé par défaut" spécifié dans le @GeneratedValue source d'annotation.
Cependant, mon raisonnement semble s'arrêter là puisque GeneratedType.AUTO a également été défini par défaut avec 1.5.1.

Une solution simple pour répondre à mes attentes est de spécifier le type de génération de stratégie IDENTITY comme ceci:

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

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

Je ne peux pas comprendre une explication de ce comportement.

Qu'est-ce que Spring-boot 2.0. a changé, expliquant ce scénario?

13
Florian Laforest

Spring Boot 2.0 utilise Hibernate 5.2 ( https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes ).
Hibernate change son GeneratedType.AUTO stratégie depuis 5.2. Toute base de données qui ne prend pas en charge les séquences nativement (par exemple MySQL), elles utilisent le générateur TABLE au lieu d'IDENTITY. ( https://hibernate.atlassian.net/browse/HHH-11014 )

Voilà pourquoi GeneratedType.AUTO ne fonctionne pas comme prévu.

12
Min Hyoung Hong

Comme Andrew l'a souligné dans le commentaire, si vous ne voulez pas que l'ID soit incrémenté pendant que les valeurs sont créées dans d'autres tables, vous pouvez spécifier votre ID comme ceci:

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

En faisant cela, chaque table aura son identifiant unique commençant par 1,2,3 ... et ainsi de suite.

0
Gastón Saillén

Si vous avez besoin d'une solution rapide et non évolutive pour éviter ce problème:

spring.jpa.hibernate.use-new-id-generator-mappings=false, à partir des documents Spring Boot 2:

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

Cela empêchera d'utiliser les nouveaux générateurs et conservera les anciennes fonctionnalités incluses dans Spring boot 1.x.x.

Veuillez noter que ce n'est probablement pas la meilleure solution, mais c'est très utile à court terme

0
Nick