我的主要密钥实体如下所示
@GeneratedValue(strategy= GenerationType.TABLE)
private Long id;
当我跑步时,我收到错误
无法获取或更新下一个值;嵌套异常是org.hibernate.exception.SQLGrammerException:无法获取或更新下一个值
但是当我改为
时@GeneratedValue
private Long id;
没有错误抛出。我想在 oracle db上为每个表生成唯一的主键。
答案 0 :(得分:29)
@GeneratedValue(strategy=GenerationType.TABLE)
告诉JPA提供程序在将新创建的实体插入数据库时使用表来获取ID。
当使用Hibernate作为提供者时,这将产生一个表hibernate_sequences
,它有两列:实体名称和已分配给该实体的最大标识。在这里,似乎Hibernate没有成功为你的实体获取它的下一个ID,但很难说确切原因,因为你没有提供足够的信息。
那么,你能提供完整的堆栈跟踪吗?另外,请将hibernate.show_sql
属性设置为true
的日志记录设置为log4j.logger.org.hibernate.SQL=DEBUG
并设置正确的日志级别hibernate.dialect
。如果可能,请将日志加入您的问题。
也许只是检查一下是否为Oracle配置了正确的GenerationType.AUTO
。实际上,如果可能的话,也加入你的休眠配置。
SEQUENCE
为您的数据库类型猜测最佳策略,或者使用GenerationType.AUTO
强制它)但是我假设您希望结果数据结构与数据库无关。如果没有,我建议改用序列。
编辑:回答OP关于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;
并仍然控制数据库使用序列的情况下序列的名称:
{{1}}
换句话说,您可以为每个表使用不同的序列名称,而不会丢失可移植性。
答案 1 :(得分:9)
JPA中有4种自动生成策略:
对于Oracle自动生成主键注释,可以选择Sequence和Table。基本逻辑是首先定义生成器,分别使用 @SequenceGenerator 或 @TableGenerator ,然后在 @GeneratedValue 中使用生成器作为属性。 / p>
这是如何使用序列策略的示例:
@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的教程。