Hibernate generates negative id values when using a sequence

38,583

Solution 1

I just ran into this issue when migrating from JBoss 6.1 to JBoss 7.1.

According to the JBoss AS 7.1 JPA documentation ( https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties),

JBoss 7.1 automatically sets several hibernate properties. One of the properties being set is hibernate.id.new_generator_mappings which activates new ID generators that use different algorithms and are not backwards compatible. Setting this property to false in your persistence.xml file will restore the old ID generator behavior.

The hibernate 4 documentation also has information regarding the new ID generators: http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#mapping-declaration-id-generator.

The hibernate documentation clearly states that the new ID generators are not enabled by default, but, as noted above, JBoss 7.1 is automatically enabling them.

Solution 2

The new behaviour is the followings:

AllocationSize is a range of primary key values reserved for Hibernate. And the select seq.nextval from dual will be done only after hibernate consumed this range of primary keys.

So you must declare the same value on both allocationSize (Hibernate) and sequence increment by (DB)

When explicitly set allocationSize=500, e.g. on Oracle

create sequence SEQ_ACE_WORKERS_QUEUE_STATS_ID
       MINVALUE 1 
       MAXVALUE 999999999999999999999999999 
       START WITH 1
       INCREMENT BY 500 
       NOCACHE 
       NOCYCLE;

Otherwise, you'll notice negative values or constraint errors raised from your DB because of primary key collisions.

When the app server is restarted, you'll notice the 'jump' between the latest primary key allocated, and the 'newly' sequence number selected at restart.

Final comment: default value is 50. So if you don't specify allocationSize on the Hibernate side, you must declare increment by 50 on the DB side.

Solution 3

Setting hibernate.id.new_generator_mappings to false in my persistence.xml was just the first part of the solution to my problem:

To completely solve the problem I added the allocationSize to 1 in the @SequenceGenerator (which I was omitting).

Share:
38,583

Related videos on Youtube

Tomer
Author by

Tomer

Updated on July 09, 2022

Comments

  • Tomer
    Tomer almost 2 years

    I have a class with the following definition:

    @Id
    @SequenceGenerator(name = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", sequenceName = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", allocationSize = 500)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACE_WORKERS_QUEUE_STATS_ID")
    @Column(name = "ID")
    private long Id;
    

    When we ran it on Jboss 4.2.3 it worked fine and generated the proper ID's (starting from 1000+)

    Now we moved to jboss 7.1.1 and it generates negative ID's! (starting from -498 and going up)

    Any idea why this might happen?

    • HRgiger
      HRgiger about 12 years
      did you check what is current sequence in Oracle and trace hibernate output, if you see proper select next sequence query and if you copy paste into sqlplus you get the correct/same/expected result?
  • Tomer
    Tomer almost 12 years
    Thanks for the answer, I already managed to find it, forgot to update it here :(
  • Markus Pscheidt
    Markus Pscheidt over 6 years
    Starting with Hibernate version 5.0, the hibernate.id.new_generator_mappings property defaults to true. See docs.jboss.org/hibernate/orm/5.2/userguide/html_single/…
  • Markus Pscheidt
    Markus Pscheidt over 6 years
    Very useful answer, as this information apparently isn't in the Hibernate docs.
  • Spork
    Spork over 5 years
    but why did you have to add both? What part of the new_generator_mappings besides the allocationSize change gave an issue that was solved by setting it to false?
  • falsarella
    falsarella over 5 years
    Setting to false just worked after setting allocationSize
  • MrtN
    MrtN almost 4 years
    This helped me a lot. I couldn't get the @SequenceGenerator to work, because I kept getting negative values and constraint errors. Just adding allocationSize = 1 solved it. I am using PostgreSQL.