J'ai une table avec une colonne simple d'id int avec l'incrémentation automatique d'identité dans SQL Server.
L'identité de l'entité est annotée avec @Id
et @GeneratedValue
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
Dans SQL Server, la colonne est correctement définie en tant qu'identité avec Seed
et Increment
égal à 1.
Lorsque j'essaie de conserver une instance de cette entité, Hibernate essaie d'interroger la table hibernate_sequence pour obtenir la valeur de l'ID. Comme je n'ai pas créé cette table dans mon schéma, je reçois une erreur:
could not read a hi value: com.Microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'MySchema.hibernate_sequence'
Si je change le type de génération en IDENTITÉ, tout fonctionne comme prévu
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
Je ne peux pas le changer de cette façon, car mon application s'exécutera à la fois sur MS SQL et Oracle, et ce dernier ne prend pas en charge les colonnes incrémentées automatiquement.
Autant que je sache, le type AUTO doit utiliser le comportement d'incrémentation automatique si la base de données sous-jacente est prise en charge. Je ne sais donc pas pourquoi ne fonctionne pas.
METTRE À JOUR:
Cela m'a pris du temps mais j'ai pu comprendre exactement ce qui se passait.
Je travaille avec des bases de données existantes avec les comportements suivants:
Voici le résultat de l'utilisation de certaines stratégies de génération d'identifiant:
Il me faut donc trouver un moyen de configurer cette entité pour:
Cela peut entraîner de graves problèmes sur Oracle lorsque je dois insérer des entités dépendant de l'entité principale (via une clé étrangère), car Hibernate ne saura pas quelle valeur d'ID a été générée par le déclencheur "external".
J'ai eu un problème similaire et j'ai trouvé cette information (expliqué plus en détail dans ici ).
L'ajout de cette propriété dans mon fichier persistence.xml a résolu le problème suivant:
<property name="hibernate.id.new_generator_mappings" value="false" />
Orcale 12c prend en charge IDENTITY et SQL SERVER 2012 prend en charge SEQUENCES. Je crois qu'un SEQUENCE est toujours un meilleur choix qu'un IDENTITY . IDENTITY désactive le traitement par lots et SEQUENCES vous permet de fournir des optimiseurs, tels que la stratégie d'optimisation pooled-lo .
Voici comment le générateur d'identifiant réel est choisi pour la valeur GenerationType configurée:
switch ( generatorEnum ) {
case IDENTITY:
return "identity";
case AUTO:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "native";
case TABLE:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.TableGenerator.class.getName()
: MultipleHiLoPerTableGenerator.class.getName();
case SEQUENCE:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "seqhilo";
}
Si vous utilisez les nouveaux identificateurs générateurs :
properties.put ("hibernate.id.new_generator_mappings", "true");
L’automate utilisera en fait un SequenceStyleGenerator et si la base de données ne prend pas en charge les séquences, vous finissez par utiliser un générateur TABLE (solution portable mais moins efficace que IDENTITY ou SEQUENCE).
Si vous utilisez les générateurs d'identifiants hérités, vous obtenez alors la stratégie de génération "native", à savoir:
public Class getNativeIdentifierGeneratorClass() {
if ( supportsIdentityColumns() ) {
return IdentityGenerator.class;
}
else if ( supportsSequences() ) {
return SequenceGenerator.class;
}
else {
return TableHiLoGenerator.class;
}
}
Si un nouvel Oracle12gDialect doit être ajouté et prend en charge IDENTITY, alors AUTO peut basculer sur IDENTITY plutôt que sur SEQUENCE, ce qui pourrait éventuellement dépasser vos attentes actuelles. À l'heure actuelle, aucun dialecte de ce type n'est disponible, vous avez donc SEQUENCE sur Oracle et IDENTITY dans MSSQL.
Conclusion:
Essayez comme ça:
@Id
@GenericGenerator(name = "native_generator", strategy = "native")
@GeneratedValue(generator = "native_generator")
private Long id;
Si votre système existant utilise une table pour générer des valeurs de séquence et qu'aucune optimisation hilo n'a été utilisée, vous pouvez utiliser un générateur d'identificateur de table:
@Id
@GeneratedValue(generator = "table", strategy=GenerationType.TABLE)
@TableGenerator(name = "table", allocationSize = 1
)
private Long id;
Vous pouvez également utiliser le générateur de table JPA. Assurez-vous simplement de configurer le bon optimiseur. Pour plus d'informations, consultez mon tutoriel Hibernate
parce que
@GeneratedValue(strategy = GenerationType.AUTO)
utiliser SequenceStyleGenerator
par défaut dans les versions antérieures
vous devez regarder ceci https://hibernate.atlassian.net/browse/HHH-11014