J'ai une base de données Oracle héritée avec une séquence nommée PRODUCT_ID_SEQ
.
Voici le mappage de la classe Product
pour laquelle j'ai besoin de générer des identifiants corrects:
public class Product {
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "retailerRaw_seq")
@SequenceGenerator(name = "retailerRaw_seq",
sequenceName = "PRODUCT_ID_SEQ")
private Long id;
...
}
Mais on dirait que les ids sont générés avec un intervalle de 50, comme 1000, 1050, 1100, etc. Cela correspond à la valeur par défaut de allocationSize
propriété = 50. Cela signifie donc que Hibernate n'utilise pas la séquence déjà définie dans le db.
Comment faire pour que Hibernate utilise la séquence?
La réponse à la question initiale:
@SequenceGenerator(name="EL_SEQ", sequenceName="EL_SEQ",allocationSize=1)
C'est allocationSize
qui définit la valeur à incrémenter.
Je ne suis pas habitué à utiliser des annotations, c'est ce que j'ai dans mon * .hbm.xml:
<id name="id" type="Java.lang.Integer">
<column name="ID_PRODUCT" />
<generator class="sequence-identity" >
<param name="sequence">PRODUCT_ID_SEQ</param>
</generator>
</id>
Vous pouvez facilement mapper cela en annotations. Le générateur sequence-identity utilise l'incrémentation automatique avec les séquences.
Voici un exemple de travail avec des annotations. Ainsi, la séquence de base de données existante sera utilisée (vous pouvez également utiliser la stratégie "séquence" mais avec moins de performances lors de l'insertion):
@Entity
@Table(name = "USER")
public class User {
// (...)
@GenericGenerator(name = "generator", strategy = "sequence-identity", parameters = @Parameter(name = "sequence", value = "USER_SEQ"))
@Id
@GeneratedValue(generator = "generator")
@Column(name = "ID", unique = true, nullable = false, precision = 22, scale = 0)
public Long getId() {
return this.id;
}
Créez votre nom de séquence dans Oracle, par exemple, contacts_seq . Dans votre classe POJO. Définissez l'annotation suivante pour votre séquence.
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_seq_gen")
@SequenceGenerator(name="my_seq_gen", sequenceName="contacts_seq")
J'ai eu le même problème lors de la mise à niveau de 3.5.5 à 5.0.6.Final.
Je l'ai résolu en reconfigurant le mappage dans le fichier HBM à partir de:
<generator class="sequence">
<param name="sequence">PRODUCT_ID_SEQ</param>
</generator>
à:
<generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
<param name="prefer_sequence_per_entity">true</param>
<param name="optimizer">none</param>
<param name="increment_size">1</param>
<param name="sequence_name">PRODUCT_ID_SEQ</param>
</generator>
Si vous utilisez javax.persistence.SequenceGenerator, mettez en veille hibernate et utilisez hilo, ce qui risque de créer de grandes lacunes dans la séquence. Il existe un message traitant de ce problème: https://forum.hibernate.org/viewtopic.php?t=973682
il y a deux façons de résoudre ce problème
Dans l'annotation SequenceGenerator, ajoutez allocationSize = 1, initialValue = 1
au lieu d'utiliser javax.persistence.SequenceGenerator, utilisez org.hibernate.annotations, comme ceci:
@ javax.persistence.SequenceGenerator (name = "Question_id_sequence", sequenceName = "S_QUESTION")
@ org.hibernate.annotations.GenericGenerator (name = "Question_id_sequence", strategy = "sequence", parameters = {@Parameter (name = "sequence", value = "S_QUESTION")})
J'ai testé les deux méthodes, ce qui fonctionne très bien.
allocationSize et incrementBy sont des choses complètement différentes.
Hibernate utilise bien sûr votre séquence créée dans une base de données, mais en fonction de allocationSize, vous pouvez trouver un écart dans la valeur générée.
Par exemple, Supposons que la séquence actuelle soit égale à 5, incrémente de 1 dans db et allocationSize default 50.
Maintenant, vous voulez sauvegarder une collection de 3 éléments via Hibernate, puis Hibernate assignera les identifiants générés 250, 251, 252
C'est à des fins d'optimisation. Hibernate n'a pas besoin de retourner à la base de données et d'extraire la prochaine valeur incrémentée.
Si vous ne voulez pas cela, il suffit de mettre allocationSize = 1
comme déjà répondu
J'utilise le suivant sur PostgreSQL et fonctionne très bien.
@Id
@GeneratedValue(generator = "my_gen")
@SequenceGenerator(name = "my_gen", sequenceName = "my_seq_in_db")
private int userId;
Tout d'abord: vous devez créer dans votre base de données la séquence suivante:
CREATE SEQUENCE "PRODUCT_ID_SEQ" MINVALUE 0 MAXVALUE 1000000000 INCREMENT BY 1 START WITH 1 CACHE 500 NOORDER NOCYCLE ;
et dans votre fichier, la configuration de Product.hbm.xml:
<class name="ProductPersistant" table="Product">
<id name="id" type="Java.lang.Long" column="productID" >
<generator class="sequence">
<param name="sequence">PRODUCT_ID_SEQ</param>
</generator>
</id>
Par défaut, Hibernate utilise le générateur de séquence HiLo qui, sauf si vous avez des besoins particuliers, est bon (en termes de performances). Vous pouvez en lire plus sur mon blog ici
Eyal