hibernate oracle序列产生很大的差距

我使用的是hibernate 3,oracle 10g。 我有一张桌子:主题。 定义在这里

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

当插入一个新的主题,sub_seq被用来创build一个主题ID,定义在这里

 create sequence sub_seq MINVALUE 1 MAXVALUE 999999999999999999999999999 START WITH 1 INCREMENT BY 1 CACHE 100 NOCYCLE ; 

Subject类是这样的:

 @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; } 

在主题表中,数据库中有4555个主题由excel中的plsql脚本加载,而sub_sequence工作正常。 主题ID范围从1-4555。

然而,当我从我的应用程序使用hibernate添加一个主题时,序列号跳到255050.运行几天后,hibernate产生的主题ID看起来像这样

 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 

有几个大的差距:4555至255051,255067至260051,265057至270051

这是浪费,而不是一个理想的行为。

有谁知道为什么会发生这种情况,而且很难修复

谢谢

我认为这个问题来自序列生成器并不是一个序列生成器,而是一个序列hilo生成器,默认分配大小为50,如文档所示: http ://docs.jboss.org/ 冬眠/稳定/注解/参考/ EN / html_single /#实体-映射标识符

这意味着如果序列值是5000,则下一个生成的值将是5000 * 50 = 250000.将序列的caching值添加到方程中,可能会解释您的初始缺口。

检查序列的值。 它应该小于最后生成的标识符。 注意不要将序列重新初始化为最后生成的值+ 1,因为生成的值将呈指数级增长(我们遇到了这个问题,并且由于溢出而产生负整数ID)

同意JB。 但还是要感谢PaulJ。

为了更具体到我的注释代码如下:

 @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; } 

如果你使用javax.persistence.SequenceGenerator ,hibernate使用hilo并且可能会在序列中产生很大的空白。 有一个post解决了这个问题: https : //forum.hibernate.org/viewtopic.php?t=973682

有两种方法可以解决这个问题

  1. 在SequenceGenerator批注中,添加allocationSize = 1, initialValue= 1
  2. 而不是使用javax.persistence.SequenceGenerator,使用org.hibernate.annotations,如下所示:

     @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") } ) 

我已经testing了两种方式,这工作得很好。

另一个解决scheme是

使用'strategy = GenerationType.AUTO'而不是'strategy = GenerationType.SEQUENCE',如下所示

 @Id @SequenceGenerator(name = "studentId", sequenceName = "student_Id") @GeneratedValue(strategy = GenerationType.AUTO, generator="studentId") private int studentId; 

如果您阅读以下链接,则会看到问题是由序列创build命令中的CACHE设置引起的。 删除caching设置将在一定程度上解决问题 – 但不考虑回滚的可能性等。

链接是: http : //asktom.oracle.com/pls/apex/f? p=100:11:0 ::::P11_QUESTION_ID : 369390500346406705

现在重新同步序列的唯一方法是重新创build序列,重命名当前表并重新创build表,然后将旧表中的logging重新插入到新表中。

注意:序列的caching值对于一次分配“x”序列值的大负载很有用。 如果你使用的是一个插入的交易系统 – 那么caching是没有用的(或者我应该说 – 我从来没有发现它有用)。

注意:这是我对序列的caching选项的理解。 您可以在CREATE SEQUENCE命令中查找Oracle文档以获取更多信息。 但上面的链接应该为您的问题提供合理的答案。

谢谢。 保罗

实际上,如果您的序列INCREMENT VALUE为1,并且您不需要坚持很多实体,那么allocationSize = 1就可以了。 然而,如果你想坚持成千上万的logging ,上述设置可能会成为一个性能瓶颈,因为每个保存需要获取一个ID因此需要一个数据库读取。

为了解决这个问题,我们需要将allocationSize设置为500,并将DB中的INCREMENT VALUE也设置为500,最重要的是添加一个hibernate.id.new_generator_mappings来请求它使用新的序列生成器实现,这里我假设你在java Config类中设置你的hibernate属性:

 properties.setProperty("hibernate.id.new_generator_mappings", Boolean.toString(true)); 

这样,Hibernate将使用SequenceStyleGenerator而不是使用旧的SequenceHiLoGenerator生成id。 SequenceStyleGenerator更加jpa和oracle友好。 它基于序列式数据库结构生成标识符值。 变化范围从实际使用序列到使用表来模仿序列。

如果您在同一条船上,请查看我的post以获取更多详细信息:

vcfvct.wordpress.com/2016/04/23/jpa-sequencegenerator-with-allocationsize-1-performance-tuning/

最成功的答案是:

 @Id @SequenceGenerator (name = "id_sequence", sequenceName = "sq50") @GeneratedValue(strategy = GenerationType.AUTO, generator = "id_sequence") public int getId() { return id; } 

我有类似的问题。 序列发生器和序列hilo发生器非常相似,但有区别。 在hibernate3中,hilo生成器乘以默认值50.因此,不需要增加DB序列。 另一方面,更高版本的hibernate默认使用序列生成器。 因此DB需要增加50。

https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.3/html/Migration_Guide/Preserve_the_Existing_Behavior_of_the_Hibernate_Identity_Auto_Generated_Value1.html

我有这个问题有多个hibernate版本(3和5)。 相同的configuration工作正常(在数据库中增加1)。 但在hibernate5失败。因此,我更新我的persistence.xml如下。 这确保了希洛一代

  <property name="hibernate.id.new_generator_mappings" value="false" /> 

如上所述,尝试使用数据库序列INCREMENT BY数字调整SequenceGenerator.allocationSize

Interesting Posts