53

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?

falsarella
  • 12,217
  • 9
  • 69
  • 115
Tomer
  • 17,787
  • 15
  • 78
  • 137
  • 1
    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? – HRgiger Mar 25 '12 at 15:50

5 Answers5

94

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.

user2418306
  • 2,352
  • 1
  • 22
  • 33
skay
  • 1,681
  • 1
  • 14
  • 13
  • 6
    Very useful answer, as this information apparently isn't in the Hibernate docs. – Markus Pscheidt Oct 28 '17 at 12:11
  • 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. – MrtN May 27 '20 at 09:22
38

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.

RThomas
  • 10,702
  • 2
  • 48
  • 61
jrm
  • 496
  • 4
  • 3
  • Thanks for the answer, I already managed to find it, forgot to update it here :( – Tomer May 20 '12 at 10:27
  • 2
    Starting with Hibernate version 5.0, the `hibernate.id.new_generator_mappings` property defaults to `true`. See http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators – Markus Pscheidt Oct 28 '17 at 10:50
27

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

falsarella
  • 12,217
  • 9
  • 69
  • 115
1

We run into a simliar error but with a (presumeably) different reason:

We dont' define allocationSize explicitly (and therefor have the default value of 50). We had our application running but than dropped the database and re-created it. Hibernate had his id-cache, used all of it, then communicated with the database to get new ids.

Now the hibernate-id cache was at least at 50 (might have been a lot higher for some tables), but the database dropped, rebuilt and is now empty. So there was some inconsistency already ... but for whatever reason hibernate then started the next round of ids at -48.

We run into a follow-up-error because our entities had ids defined with datatype int instead of Integer and when hibernate continued counting up and reached the entity with 0 it thought, that it is not in the database yet, tried to make an INSERT instead of an UPDATE and got a key validation error.

I still can't explain why hibernate decides to start the keys at -48 when running into this inconsistency ... but for us the error could be solved by simply shutting down the aplication before changing sequences in the database. Also all our entities now use Integer instead of int for ids.

Hope this information is helpful for someone out there.

Mathias Bader
  • 3,585
  • 7
  • 39
  • 61
0

Use in your entity the strategy SEQUENCE @GeneratedValue(strategy = GenerationType.SEQUENCE)

and create the sequence in database with increment by 50, follow exemple: create sequence <sequence> increment by 50;