JBoss EAP 6.x repeating sequence Oracle Hibernate Oracle Primary Key

I defined a number of hibernation objects using pure JPA annotations. They use the predefined Oracle sequence in my database to automatically generate primary key values.

@Id @SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_ID_GENERATOR") @Column(name = "U_ID", updatable = false, unique = true, nullable = false, precision = 19) private Long id; 

When this is deployed to JBoss EAP 6.1, everything works fine, but after a short period, Hibernate starts generating duplicate keys on inserts (errors ORA-00001).

I don't need orderings or id spaces, but you cannot tolerate duplicate keys ... What is happening here?

+6
source share
2 answers

This is poorly documented, many of the solutions here and other sites relate to older versions of sleep mode, where the HiLo sequence generator was installed by default. But after the investigation, I found that the main reason is that JBoss EAP 6 installs

 hibernate.id.new_generator_mappings=true 

by default, which uses org.org.hibernate.id.enhanced.SequenceStyleGenerator instead of the old version.

The default value for the Hibernate SequenceStyleGenerator is 1 (check the code!), However the JPA overrides the increment value in this generator to 50. This means that the generator scans the next sequence and stores a cache of 50 identifiers to use, starting from nextval - 49. When they exhausted, the generator reads the next sequence from the oracle and repeats the process. Therefore, when the first series of identifiers is exhausted, we begin to see duplicate keys.

So the resolution is:

1) Define an Oracle sequence with an incremental value of 50 to comply with the JPA default

 CREATE SEQUENCE MY_SEQ START WITH 50 MAXVALUE 9999999999999999999 INCREMENT BY 50 NOCYCLE; 

or

2) Add allocSize = 1 to the @SequenceGenerator annotation - this will make SequenceGenerator go back to read the next value from the oracle sequence for each required identifier (with potential impact)

  @SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ", allocationSize = 1) 

or

3) define the sequence of Oracle INCREMENT with a different value and make sure matchSize matches.

He answered my own question in the hope of helping others who were faced with this problem.

+13
source

Your answers are correct; just some details.

Some posts suggest disabling hibernate.id.new_generator_mappings = false.

But according to https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties

There is a difference between GenerationType.AUTO and GenerationType.SEQUENCE

if you select AUTO, you will select sleep mode. and if you choose SEQUENCE, you will find the hilo algorithm for the distribution of sequences, which is completely different from the SequenceStyleGenerator. This will NOT be compatible if you switch hibernate.id.new_generator_mappings = true / false.

So the answer 1) is definitely correct / following current Hibernate / Jboss recommendations.

... and distributing answers allocize = 1 for all objects is not a good solution. See http://itdevworld.wordpress.com/2009/12/20/hibernate-sequencegenerator-with-allocationsize1-leads-to-huge-contention/

+1
source

Source: https://habr.com/ru/post/950151/


All Articles