J'ai une classe avec la définition suivante:
@Id
@SequenceGenerator(name = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", sequenceName = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", allocationSize = 500)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACE_WORKERS_QUEUE_STATS_ID")
@Column(name = "ID")
private long Id;
Lorsque nous l'avons exécuté sur Jboss 4.2.3, cela a bien fonctionné et généré les ID appropriés (à partir de 1000+)
Maintenant, nous sommes passés à jboss 7.1.1 et il génère des ID négatifs! (à partir de -498 et en remontant)
Une idée pourquoi cela pourrait arriver?
Je viens de rencontrer ce problème lors de la migration de JBoss 6.1 vers JBoss 7.1.
Selon la documentation JBoss AS 7.1 JPA ( https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties ),
JBoss 7.1 définit automatiquement plusieurs propriétés d'hibernation. L'une des propriétés définies est hibernate.id.new_generator_mappings
qui active de nouveaux générateurs d'ID qui utilisent différents algorithmes et ne sont pas rétrocompatibles. La définition de cette propriété sur false dans votre fichier persistence.xml restaurera l'ancien comportement du générateur d'ID.
La documentation hibernate 4 contient également des informations concernant les nouveaux générateurs d'ID: http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#mapping-declaration-id-generator .
La documentation de mise en veille prolongée indique clairement que les nouveaux générateurs d'ID ne sont pas activés par défaut, mais, comme indiqué ci-dessus, JBoss 7.1 les active automatiquement.
Le nouveau comportement est le suivant:
AllocationSize est une plage de valeurs de clé primaire réservée à Hibernate. Et sélectionnez seq.nextval
à partir du double ne sera effectué qu'après que l'hibernation aura consommé cette plage de clés primaires.
Donc vous devez déclarer la même valeur à la fois sur allocationSize
(Hibernate) et sur la séquence increment by
(DB)
Lorsque explicitement défini allocationSize=500
, par exemple. sur Oracle
create sequence SEQ_ACE_WORKERS_QUEUE_STATS_ID
MINVALUE 1
MAXVALUE 999999999999999999999999999
START WITH 1
INCREMENT BY 500
NOCACHE
NOCYCLE;
Sinon, vous remarquerez des valeurs négatives ou des erreurs de contrainte générées à partir de votre base de données en raison de collisions de clés primaires.
Lorsque le serveur d'applications est redémarré, vous remarquerez le "saut" entre la dernière clé primaire allouée et le "nouveau" numéro de séquence sélectionné au redémarrage.
Commentaire final: la valeur par défaut est 50. Donc si vous ne spécifiez pas allocationSize
du côté Hibernate, vous devez déclarer increment by
50 côté DB.
Réglage hibernate.id.new_generator_mappings
à false
dans mon persistence.xml
n'était que la première partie de la solution à mon problème:
Pour résoudre complètement le problème, j'ai ajouté le allocationSize
à 1
dans le @SequenceGenerator
(que j'omettais).