JPA主键自动生成

我的主要密钥实体如下所示

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

当我跑,我得到错误

无法获取或更新下一个值;嵌套exception是org.hibernate.exception.SQLGrammerException:无法获取或更新下一个值

但是当我改变的时候

 @GeneratedValue private Long id; 

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

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

当使用Hibernate作为提供者时,这将产生一个表hibernate_sequences ,它有两列:实体名称和已分配给该实体的最大标识。 在这里,似乎Hibernate没有成功为你的实体获取它的下一个ID,但很难说确切原因,因为你没有提供足够的信息。

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

也许只是检查一下你是否为Oracle配置了正确的hibernate.dialect 。 实际上,如果可能的话,也加入你的hibernate配置。

PS:使用Oracle生成PK的“传统”方法是使用序列(您可以让Hibernate使用GenerationType.AUTO为您的数据库类型猜测最佳策略或使用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; 

换句话说,您可以使用为每个表使用不同的序列名称而不会丢失可移植性。

JPA中有4种自动生成策略:

  • 汽车
  • 身分
  • 序列

对于Oracle自动生成主键注释,可以选择Sequence和Table。 基本逻辑是首先定义生成器,分别使用@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注释可以正常工作之前,表生成器还需要您在表中插入一行。

以下是有关如何在JPA for Oracle数据库中配置主键自动生成的教程。