web-dev-qa-db-fra.com

Comment utiliser une séquence Oracle existante pour générer un identifiant dans hibernate?

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?

24
Vladimir

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.

24
Mike Demenok

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.

17
rsilva4

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;
    }
8
Tristan

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")
5
user1256936

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>
5
jvergara

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

  1. Dans l'annotation SequenceGenerator, ajoutez allocationSize = 1, initialValue = 1

  2. 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.

4
Maninder

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

2
shakhawat

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;
1
Summer

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>
0
bedjaoui djounaydi


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

0
Eyal Lupu