2009-11-30 94 views
10

我的主键实体看起来像下面JPA主键自动生成

@GeneratedValue(strategy= GenerationType.TABLE) 
private Long id; 

当我运行,我得到错误

无法获得或更新下一个值;嵌套的例外是org.hibernate.exception。 SQLGrammerException:无法获得或更新下一个值

但是当我刚刚更改为

@GeneratedValue 
private Long id; 

没有错误抛出。我想在每个表上为oracle db生成唯一的主键。

回答

28

@GeneratedValue(strategy=GenerationType.TABLE)告诉JPA提供者在将新创建的实体插入数据库时​​使用表来获取ID。

当使用Hibernate作为提供者时,这会产生一个表hibernate_sequences,它有两列:实体名称和已经分配给该实体的最大身份。在这里,看起来Hibernate没有成功从您的实体获取下一个ID,但很难说明原因,因为您没有提供足够的信息。

那么,您能否提供完整的堆栈跟踪?此外,请将hibernate.show_sql属性设置为true,并设置正确的日志级别log4j.logger.org.hibernate.SQL=DEBUG。如果可能的话,加入日志到你的问题。

也许只是检查您是否为Oracle配置了正确的hibernate.dialect。实际上,如果可能的话,加入你的休眠配置。 PS:使用Oracle生成PK的“传统”方法是使用序列(您可以让Hibernate使用GenerationType.AUTO或使用SEQUENCE强制使用SEQUENCE来推测您的数据库类型的最佳策略),但我会假设您需要结果数据结构是数据库不可知的。如果没有,我会建议去替代序列。

编辑:回答评论从OP约GenerationType.AUTO。事实上,默认值是一个叫做hibernate_sequence的单一全局序列,这可能是一个问题。但是,如下所示的设置,您可以使用GenerationType.AUTO,仍然控制的情况下,序列的名称,其中数据库采用序列:

@Id 
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_entity_seq_gen") 
@SequenceGenerator(name="my_entity_seq_gen", sequenceName="MY_ENTITY_SEQ") 
private long id; 

换句话说,你可以使用使用不同的序列名称为每个表没有失去可移植性。

+2

如果我把GenerationType.Auto,它将使用全局增量数,意味着我所有的实体将增加相同的数字。代码运行正常,但它会用完增量数字吗? – cometta 2009-11-30 04:53:54

+0

@Pascal:如果我们提供了一个SequenceGenerator,它是否有助于将Startegy指定为AUTO? – Nrj 2009-11-30 05:36:51

+0

@Nrj实际上,如果你使用'AUTO'并且数据库使用序列,'@ SequenceGenerator'将有助于控制序列的名称。但是,如果数据库不存在,它将被“忽略”(例如使用HSQLDB)。所以,与'SEQUENCE'不同,这是可移植的。 – 2009-11-30 05:49:52

7

有自动生成4个策略JPA:

  • 自动
  • 身份
  • 序列

对于Oracle自动生成主键注释,序列和表是你的选择。基本逻辑是首先定义一个发生器,分别使用@SequenceGenerator@TableGenerator,然后在@GeneratedValue处使用发生器作为属性。

这是如何使用序列的策略的示例:

@Id 
    @SequenceGenerator(name="SEQ_GEN", sequenceName="SEQ_JUST_FOR_TEST", allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_GEN") 
    private long id; 

下面是如何使用表策略的示例:

@Id 
    @TableGenerator(name="TABLE_GEN",table="T_GENERATOR", pkColumnName = "GEN_KEY", pkColumnValue = "MONITOR2012.T_JUST_FOR_TEST", valueColumnName = "GEN_VALUE", initialValue = 1, allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.TABLE, generator="TABLE_GEN") 
    private long id; 

如果@GeneratedValue注解没有指定发生器,选择将留给JPA实施。

如果您正在使用现有表的数据库,请在运行应用程序之前确保数据库中定义的序列或表。 表生成器还需要您在@GeneratedValue注释正常工作之前向表中插入一行。

这里是关于how to configure primary key auto generation in JPA for Oracle database的教程。