2013-08-27 34 views
13

我有一个问题,我无法得到我的头。在Hibernate中我有以下没有问题:EclipseLink和序列生成器预分配

@GeneratedValue(strategy = GenerationType.AUTO, generator = "email-seq-gen") 
@SequenceGenerator(name="email-seq-gen", sequenceName="EMAIL_SEQ_GEN", allocationSize=500) 

然后在我的schema.ddl我有这样的:

CREATE SEQUENCE EMAIL_SEQ_GEN START 1 INCREMENT 500; 

没有太多的看这里。一切都按预期工作。但是,如果将我的供应商的EclipseLink我得到这个错误:

The sequence named [EMAIL_SEQ_GEN] is setup incorrectly. Its increment does not match its pre-allocation size. 

所以我当然是谷歌四周,看到一些有关的EclipseLink创建一个负数,如果初始值是1,它应该等于allocationSize。

所以,好吧,所以添加“initialValue = 500”并更新我的DDL脚本为“START 500”可以解决此问题,但现在我的编号从500开始,而不是从1开始。这是一个EclipseLink错误还是有我不理解的东西。我想要生成从1开始的序列,并将分配大小调整为实体(本例中为500)。我如何使用EclipseLink来做到这一点?

谢谢!

另一种方式来问这个是....这给出DDL:

CREATE SEQUENCE EMAIL_SEQ_GEN START 1 INCREMENT 500; 

什么是注释我的实体与EclipseLink的使用正确的方法是什么?

如果我让EclipseLink的生成我DDL那么这样的:

@GeneratedValue(strategy = GenerationType.AUTO, generator = "email-seq-gen") 
@SequenceGenerator(name="email-seq-gen", sequenceName="EMAIL_SEQ_GEN", initialValue=1, allocationSize=500) 

会产生这样的:

CREATE SEQUENCE EMAIL_SEQ_GEN INCREMENT BY 500 START WITH 500; 

哪一种暗示,这是不可能创建一个DDL以“START WITH 1 “使用EclipseLink。

+0

如果你走另一个方向(让EclipseLink从你的实体生成DDL),它会产生什么? – DannyMo

+0

我编辑了原始文章以添加问题的答案。 –

回答

18

默认情况下,使用@SequenceGenerator注解的实体使用initialValue = 1和alocationSize = 50。

public @interface SequenceGenerator { 
    /** 
    * (Optional) The value from which the sequence object 
    * is to start generating. 
    */ 
    int initialValue() default 1; 

    /** 
    * (Optional) The amount to increment by when allocating 
    * sequence numbers from the sequence. 
    */ 
    int allocationSize() default 50; 
} 

“连续”,实体ID似乎是的EclipseLink用以下公式计算:

entityId = initialValue - allocationSize + INCREMENT_BY 

或使用DDL的情况下:

entityId = START_WITH - allocationSize + INCREMENT_BY 

再回到您的特定案例:


@SequenceGenerator( 
    name="email-seq-gen", 
    sequenceName="EMAIL_SEQ_GEN", 
    allocationSize=500 
) // initialValue=1 (default) 

CREATE SEQUENCE EMAIL_SEQ_GEN START WITH 1 INCREMENT BY 500; 

产生

entityId = 1 - 500 + 1 = -500 // EclipseLink error 

@SequenceGenerator( 
    name="email-seq-gen", 
    sequenceName="EMAIL_SEQ_GEN", 
    initialValue=1, 
    allocationSize=500) 

CREATE SEQUENCE EMAIL_SEQ_GEN START WITH 1 INCREMENT BY 500; 

产生

entityId = 1 - 500 + 1 = -500 // EclipseLink error 

@SequenceGenerator( 
    name="email-seq-gen", 
    sequenceName="EMAIL_SEQ_GEN", 
    initialValue=500, 
    allocationSize=500 
) 

CREATE SEQUENCE EMAIL_SEQ_GEN START WITH 500 INCREMENT BY 500; 

产生

entityId = 500 - 500 + 500 = 500 // fine, but inappropriate 
entityId = 500 - 500 + 1000 = 1000 // incremented by 500 
entityId = 500 - 500 + 1500 = 1500 // incremented by 500 
... 

满足您的要求应该使用下列内容:

@SequenceGenerator( 
    name="email-seq-gen", 
    sequenceName="EMAIL_SEQ_GEN", 
    allocationSize=500 
) // initialValue=1 (default) but 'START WITH'=500 

CREATE SEQUENCE EMAIL_SEQ_GEN START WITH 500 INCREMENT BY 1; 

产生

entityId = 500 - 500 + 1 = 1 
entityId = 500 - 500 + 2 = 2 
entityId = 500 - 500 + 3 = 3 
... 

现有的序列可以从下面的底层数据库中删除SQL command

DROP SEQUENCE email_seq_gen RESTRICT; 

我希望它有帮助。

+0

很高兴知道如何删除/删除创建的序列。我尝试了几种方法,但都没有工作。 – burseaner

+0

@burseaner:我添加了一个命令,用于删除一个存在的序列。 – wypieprz

+1

用增量1创建序列是错误的。 EclipseLink每个分配批次只调用一次序列(在这种情况下,对于在同一事务中添加的每500个实体一次)。 因此增量必须等于500.是的,当分配批次小于500时,数字将被跳过,但这是您为效率付出的代价,这是由于序列的调用较少。 要查看发生的错误,请添加两个实体,然后终止Java程序,然后添加另一个实体。由于重复的ID,将发生java.sql.SQLIntegrityConstraintViolationException。 – bgh

2

你的序列应在500而不是1开始如果你从1开始,那么第一个NEXTVAL只会给你1号,而不是500

设置它后否则调用NEXTVAL在序列中,因此它达到501.

错误是警告还是错误?如果你忽略它,它还能工作吗?

+1

这有什么意义?如果我编写代码池身份,我得到1,501,1001,等等。这也是我从Hibernate获得的?如果EclipseLink没有这种情况,并且(来自Google搜索),那么很多人都遇到了这个问题,为什么他们不修正这个算法呢? –

+0

哦,这不是一个警告的错误。 –