26

I have legacy Oracle db with a sequence named PRODUCT_ID_SEQ.

Here is the mapping of Product class for which I need generate correct ids:

public class Product {
   @GeneratedValue(strategy = GenerationType.SEQUENCE, 
                       generator = "retailerRaw_seq")
   @SequenceGenerator(name = "retailerRaw_seq", 
                      sequenceName = "PRODUCT_ID_SEQ")
   private Long id;

   ...
}

But looks like ids are generated with an interval of 50, like 1000, 1050, 1100 etc. This corresponds to the default value of allocationSize property = 50. So that means that Hibernate doesn't actually use the sequence which is already defined in the db.

How do I make Hibernate use the sequence?

RubioRic
  • 2,442
  • 4
  • 28
  • 35
Vladimir
  • 12,753
  • 19
  • 62
  • 77

10 Answers10

29

The answer to the original question:

@SequenceGenerator(name="EL_SEQ", sequenceName="EL_SEQ",allocationSize=1)

It is allocationSize that sets the value to increment by.

Mike Demenok
  • 791
  • 8
  • 15
  • 8
    Upvoted because this is a correct JPA solution rather than being Hibernate specific. However an allocationSize=1 means that a number needs to be obtained from the database for every insert rather than caching a lot of Ids at once, so it comes with a very small performance degradation. – shonky linux user Jul 30 '13 at 23:58
20

I'm not used to use annotations, this is what I have in my *.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>

You can easily map this to annotations. The generator sequence-identity uses auto increment with sequences.

rsilva4
  • 1,915
  • 1
  • 23
  • 39
9

Here is a working example with annotations, this way, the existing DB sequence will be used (you can also use the "sequence" strategy, but with less performance on 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;
    }
Tristan
  • 8,733
  • 7
  • 48
  • 96
  • I found when using this technique it worked but my Database was incrementing it's id value by 2 instead of 1. Any ideas why? – user898465 Oct 16 '13 at 00:05
  • check your sequence definition in Oracle, you may have something like "CREATE SEQUENCE my_sequence START WITH 1 INCREMENT BY 2" – Tristan Oct 17 '13 at 06:59
6

I had the same issue while upgrading from 3.5.5 to 5.0.6.Final.

I solved it by re-configuring mapping in the HBM file from:

    <generator class="sequence">
        <param name="sequence">PRODUCT_ID_SEQ</param>
    </generator>

to:

    <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>
jvergara
  • 101
  • 2
  • 4
5

Create your sequence name in Oracle, for example, contacts_seq. In Your POJO Class . Define the following annotation for your sequence.

@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_seq_gen")
@SequenceGenerator(name="my_seq_gen", sequenceName="contacts_seq")
Aurasphere
  • 3,841
  • 12
  • 44
  • 71
user1256936
  • 141
  • 2
  • 4
4

If you use javax.persistence.SequenceGenerator, hibernate use hilo and will possibly create large gaps in the sequence. There is a post addressing this problem: https://forum.hibernate.org/viewtopic.php?t=973682

there are two ways to fix this problem

  1. In the SequenceGenerator annotation, add allocationSize = 1, initialValue= 1

  2. instead of using javax.persistence.SequenceGenerator, use org.hibernate.annotations, like this:

    @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") } )

I have tested both ways, which works just fine.

Maninder
  • 171
  • 1
  • 3
  • 12
2

allocationSize and incrementBy are completely different things.

Hibernate is of course using your sequence created in DB but depending on allocationSize you might find gap in generated value.

For example- Let assume current sequence value is 5, increment by 1 in db, and allocationSize default 50.

Now you want to save a collection of 3 element through hibernate, then Hibernate will assign generated id 250, 251, 252

This is for optimization purpose. Hibernate doesn't have to go back to db and fetch next incremented value.

If you don't want this just setting allocationSize = 1 as already answered will do the purpose

shakhawat
  • 2,639
  • 1
  • 20
  • 36
1

I use following on PostgreSQL and works just fine.

 @Id
 @GeneratedValue(generator = "my_gen")
 @SequenceGenerator(name = "my_gen", sequenceName = "my_seq_in_db")
 private int userId;
Dhaval D
  • 1,087
  • 2
  • 14
  • 25
0


By default Hibernate uses sequence HiLo generator which ,unless you have special needs, it is good (performance wise). You can read more of that in my blog here

Eyal

Eyal Lupu
  • 822
  • 9
  • 9
  • Any idea to change algorithm, saying to pooled instead of hilo using JPA annotations? –  Oct 21 '13 at 15:57
0

First : you should create in your database the sequence like:

CREATE SEQUENCE  "PRODUCT_ID_SEQ"  MINVALUE 0 MAXVALUE 1000000000 INCREMENT BY 1 START WITH 1 CACHE 500 NOORDER  NOCYCLE ;

and in your file Product.hbm.xml configuration make :

 <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>
Robert
  • 5,278
  • 43
  • 65
  • 115