开发者

How to use existing Oracle sequence to generate id in hibernate?

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 alread开发者_StackOverflow中文版y defined in the db.

How do I make Hibernate use the sequence?


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.


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.


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


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>


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


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.


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


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;



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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜