Hibernate, @SequenceGenerator and allocSize

We all know the default behavior for Hibernate when using @SequenceGenerator - it increases the actual database sequence by one , a few this value by 50 (the default value is allocationSize ) - and then uses this value as the identifier of the object.

This behavior is incorrect and conflicts with the specification , which states:

allocSize - (Optional) The amount to increase when allocating sequence numbers from a sequence.

To be clear: I'm not worried about spaces between the generated identifiers.

I do not like identifiers not consistent with the underlying database. For example: any other application (for example, using simple JDBC) may want to insert new lines under the identifiers obtained from the sequence, but all these values โ€‹โ€‹can already be used by Hibernate! Madness.

Does anyone know of any solution to this problem (without setting allocationSize=1 and thereby reducing performance)?

EDIT:
To make everything clear. If the last inserted record had ID = 1 , then HB uses the values 51, 52, 53... for its new objects, but at the same time: the sequence value in the database will be set to 2 . This can lead to errors when other applications use this sequence.

In the hand: the specification says (in my understanding) that the database sequence should be set to 51 , and in the meantime, HB should use values โ€‹โ€‹from the range 2, 3 ... 50


UPDATE:
As Steve Ebersol mentioned: the behavior I described (as well as the most intuitive for many) can be enabled by setting hibernate.id.new_generator_mappings=true .

Thank you everybody.

UPDATE 2:
For future readers below you can find a working example.

 @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ") @SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS") private Long id; } 

persistence.xml

 <persistence-unit name="testPU"> <properties> <property name="hibernate.id.new_generator_mappings" value="true" /> </properties> </persistence-unit> 
+96
java hibernate jpa hilo
05 Oct '12 at 11:55
source share
6 answers

To be absolutely clear ... what you are describing is in no way contrary to the specification. The specification talks about the values โ€‹โ€‹that Hibernate assigns to your entities, not the values โ€‹โ€‹actually stored in the database sequence.

However, there is an opportunity to get the behavior you are looking for. First, see my answer to Is there a way to dynamically select @GeneratedValue strategy using JPA and Hibernate annotations? This will give you the basics. As long as you are configured to use this SequenceStyleGenerator, Hibernate will interpret allocationSize using the "unified optimizer" in SequenceStyleGenerator. The "Joint Optimizer" is intended for use with databases that allow you to use "increment" when creating sequences (not all databases that support sequences support growth). In any case, check out the various optimization strategies.

+34
Oct 05
source share

allocationSize=1 This is micro-optimization before receiving the request. Hibernate is trying to assign a value in the allocSize range and therefore try to avoid database queries for the sequence. But this query will be executed every time if you set it to 1. It hardly matters, because if any other application accesses your database, then it will create problems if the same identifier is used by another application .

The next generation of Sequence Identifier is based on allocSize.

By defualt, it is saved as 50 , which is too much. It will also help only if you have about 50 records in a single session that are not saved and that will be saved using this particular session and translation.

Therefore, you should always use allocationSize=1 when using SequenceGenerator . As for most basic database sequences, it always increases by 1 .

+12
05 Oct
source share

Steve Ebersole and other participants,
Could you explain the reason for id with a large gap (default is 50)? I am using Hibernate 4.2.15 and found the following code in org.hibernate.id.enhanced.OptimizerFactory cass.

 if ( lo > maxLo ) { lastSourceValue = callback.getNextValue(); lo = lastSourceValue.eq( 0 ) ? 1 : 0; hi = lastSourceValue.copy().multiplyBy( maxLo+1 ); } value = hi.copy().add( lo++ ); 

Whenever it gets inside an if statement, the value of hi becomes much larger. Thus, during testing with frequent server restarts, my identifier generates the following sequence identifiers:
1, 2, 3, 4, 19, 250, 251, 252, 400, 550, 750, 751, 752, 850, 1100, 1150.

I know that you have already said that this does not contradict the specification, but I believe that this will be a very unexpected situation for most developers.

Any input would be very helpful.

Jihwan

UPDATE: ne1410s: Thanks for editing.
cfrick: OK. I will do it. This was my first post here and was not sure how to use it.

Now I better understand why maxLo was used for two purposes: since hibernate calls the DB sequence once, keep increasing the identifier at the Java level and save it in the database, the value of the Java level identifier should take into account how much was changed without calling the database sequence when it calls sequence next time.

For example, the sequence identifier was 1 at the point, and sleep mode was 5, 6, 7, 8, 9 (with allocSize = 5). The next time we get the next serial number, DB returns 2, but hibernate should use 10, 11, 12 ... Therefore, "hi = lastSourceValue.copy (). MultiplyBy (maxLo + 1)" is used to get the next identifier 10 out of 2 returned from the database sequence. It seems that this was only during a frequent server restart, and that was my problem with a big gap.

So, when we use the SEQUENCE ID, the inserted identifier in the table will not correspond to the SEQUENCE number in the database.

+1
Sep 28 '14 at 19:46
source share

After converting to sleeping source code and Below, the configuration goes to Oracle db for the next value after 50 inserts. So every time it is called, every time it increments INST_PK_SEQ.

Sleep 5 is used for the strategy below

Check also below http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-sequence

 @Id @Column(name = "ID") @GenericGenerator(name = "INST_PK_SEQ", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { @org.hibernate.annotations.Parameter( name = "optimizer", value = "pooled-lo"), @org.hibernate.annotations.Parameter( name = "initial_value", value = "1"), @org.hibernate.annotations.Parameter( name = "increment_size", value = "50"), @org.hibernate.annotations.Parameter( name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "INST_PK_SEQ"), } ) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INST_PK_SEQ") private Long id; 
+1
Mar 03 '16 at 22:52
source share

I would check the DDL for the sequence in the schema. The JPA implementation is only responsible for creating a sequence with the correct distribution size. Therefore, if the distribution size is 50, then your sequence should have an increase of 50 in DDL.

This case can usually occur when creating a sequence with a distribution size of 1, and then setting it to a size of 50 (or default) distribution, but the DDL of the sequence is not updated.

0
Oct 05 '12 at 19:13
source share

I also came across this problem in Hibernate 5:

 @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE) @SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE) private Long titId; 

Got a warning like this below:

The use of an outdated sequence-based identifier generator has been detected [org.hibernate.id.SequenceHiLoGenerator]; use org.hibernate.id.enhanced.SequenceStyleGenerator instead. For more information, see the Hibernate Domain Model Mapping Guide.

Then changed my code to SequenceStyleGenerator:

 @Id @GenericGenerator(name="cmrSeq", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { @Parameter(name = "sequence_name", value = "SEQUENCE")} ) @GeneratedValue(generator = "sequence_name") private Long titId; 

This solved my two problems:

  1. Outdated warning fixed
  2. Now the identifier is generated according to the oracle sequence.
0
May 01 '19 at 12:57
source share



All Articles