I am using hibernate 3 , oracle 10g. I have a table: subject. The definition is here
CREATE TABLE SUBJECT ( SUBJECT_ID NUMBER (10), FNAME VARCHAR2(30) not null, LNAME VARCHAR2(30) not null, EMAILADR VARCHAR2 (40), BIRTHDT DATE not null, constraint pk_sub primary key(subject_id) USING INDEX TABLESPACE data_index ) ;
when insert a new subject, sub_seq is used to create an subject id, the definition is here
create sequence sub_seq MINVALUE 1 MAXVALUE 999999999999999999999999999 START WITH 1 INCREMENT BY 1 CACHE 100 NOCYCLE ;
the Subject class is like this:
@Entity @Table(name="ktbs.syn_subject") public class Subject { @Id @Column(name="subject_id") @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ") @SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ") private long subjectId; private String fname; private String lname; private String emailadr; private Date birthdt; }
in the subject table , there have been 4555 subjects in the database loaded by plsql scripts from excel and the sub_sequence worked fine. subject ids range from 1--4555.
however, when i added a subject from my application using hibernate, the sequence number jumped to 255050. After several days running, the subject ids generated by hibernate look like this
270079 270078 270077 270076 270075 270074 270073 270072 270071 270070 270069 270068 270067 270066 270065 270064 270063 270062 270061 270060 270059 270058 270057 270056 270055 270054 270053 270052 270051 270050 265057 265056 265055 265054 265053 265052 265051 265050 260059 260058 260057 260056 260055 260054 260053 260052 260051 260050 255067 255066 255065 255064 255063 255062 255061 255060 255059 255058 255057 255056 255055 255054 255053 255052 255051 255050 4555 4554 4553 . . . . 1
There are several large gaps: 4555 to 255051, 255067 to 260051, 265057 to 270051
this is a waste and not a desired behavior.
does anyone know why this happens and hot to fix it
Thanks
Oracle recommends using the CACHE setting to enhance performance if you are using sequences in a Real Application Clusters environment. Specify NOCACHE to indicate that values of the sequence are not preallocated. If you omit both CACHE and NOCACHE , the database caches 20 sequence numbers by default.
allocationSize - (Optional) The amount to increment by when allocating sequence numbers from the sequence.
SEQUENCE Generation. To use a sequence-based id, Hibernate provides the SequenceStyleGenerator class. This generator uses sequences if our database supports them. It switches to table generation if they aren't supported.
I think that the problem comes from the fact that the sequence generator is not really a sequence generator, but a sequence hilo generator, with a default allocation size of 50. as indicated by the documentation : http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier
This means that if the sequence value is 5000, the next generated value will be 5000 * 50 = 250000. Add the cache value of the sequence to the equation, and it might explain your huge initial gap.
Check the value of the sequence. It should be less than the last generated identifier. Be careful not to reinitialize the sequence to this last generated value + 1, because the generated valus would grow exponentially (we've had this problem, and had negative integer ids due to overflow)
Agree with JB. But still thanks to PaulJ.
To be more specific to my annotation code below:
@Entity @Table(name="ktbs.syn_subject") public class Subject { @Id @Column(name="subject_id") @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ") @javax.persistence.SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ") private long subjectId; private String fname; private String lname; private String emailadr; private Date birthdt; }
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
allocationSize = 1, initialValue= 1
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With