Nous connaissons tous le comportement par défaut de Hibernate lors de l'utilisation @SequenceGenerator
- il augmente la séquence de base de données réelle de un , multiplie cette valeur par 50 (valeur par défaut allocationSize
) - puis utilise cette valeur comme ID d'entité.
C'est un comportement incorrect et entre en conflit avec la spécification qui dit:
allocationSize - (Facultatif) Le montant à incrémenter lors de l'allocation des numéros de séquence à partir de la séquence.
Pour être clair: je ne me soucie pas des écarts entre les identifiants générés.
Je me soucie des ID qui ne sont pas cohérents avec la séquence de base de données sous-jacente. Par exemple: toute autre application (qui utilise par exemple JDBC brut) peut vouloir insérer de nouvelles lignes sous les ID obtenus à partir de la séquence - mais toutes ces valeurs peuvent déjà être utilisées par Hibernate! La démence.
Quelqu'un connaît-il une solution à ce problème (sans réglage allocationSize=1
et donc dégradation des performances)?
EDIT:
Pour clarifier les choses. Si le dernier enregistrement inséré avait ID = 1
, alors HB utilise des valeurs 51, 52, 53...
pour ses nouvelles entités MAIS en même temps: la valeur de la séquence dans la base de données sera définie sur 2
. Ce qui peut facilement conduire à des erreurs lorsque d'autres applications utilisent cette séquence.
D'un autre côté: la spécification dit (à ma connaissance) que la séquence de la base de données aurait dû être définie sur 51
et, entre-temps, HB devrait utiliser des valeurs de range 2, 3 ... 50
MISE
À JOUR: Comme Steve Ebersole l'a mentionné ci-dessous: le comportement décrit par moi (et aussi le plus intuitif pour beaucoup) peut être activé en définissant hibernate.id.new_generator_mappings=true
.
Merci à vous tous.
MISE À JOUR 2:
Pour les futurs lecteurs, vous trouverez ci-dessous un exemple fonctionnel.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
@SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
private Long id;
}
persistence.xml
<persistence-unit name="testPU">
<properties>
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
save
doit interroger la base de données pour la valeur suivante de la séquence.
SequenceGenerator
Hibernate interrogera la base de données uniquement lorsque le nombre d'ID spécifiés par allocationsize
s'épuise. Si vous configurez, allocationSize = 1
c'est la raison pour laquelle Hibernate interroge la base de données pour chaque insertion. Modifiez cette valeur et vous avez terminé.
hibernate.id.new_generator_mappings
cadre est vraiment important. J'espère que c'est le paramètre par défaut que je n'ai pas à passer autant de temps à rechercher pourquoi le numéro d'identification devient sauvage.