自动生成 JPA 主键

2022-09-02 11:50:44

我的主键实体如下所示

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

当我运行时,我得到错误

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

但是当我只是改变为

@GeneratedValue 
private Long id;

无错误抛出 。我想在预言机数据库上为每个表生成唯一的主键。


答案 1

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

使用 Hibernate 作为提供程序时,这将生成一个包含两列的表:实体名称和已分配给此实体的最大标识。在这里,似乎Hibernate无法成功地从中获取实体的下一个ID,但很难确切地说出原因,因为您没有为此提供足够的信息。hibernate_sequences

那么,您能提供完整的堆栈跟踪吗?另外,请在将属性设置为的情况下将日志记录设置为 并设置正确的日志级别 。如果可能的话,将日志加入您的问题。hibernate.show_sqltruelog4j.logger.org.hibernate.SQL=DEBUG

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

PS:使用Oracle生成PK的“传统”方法是使用序列(您可以让Hibernate猜测数据库类型的最佳策略使用或强制使用),但我假设您希望结果数据结构与数据库无关。如果没有,我建议改用序列。GenerationType.AUTOSEQUENCE

编辑:回答OP关于.实际上,默认值是调用单个全局序列,这可能是一个问题。但是,通过如下所示的设置,对于数据库使用序列的情况,您可以使用并仍然控制序列的名称:GenerationType.AUTOhibernate_sequenceGenerationType.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

JPA中有4种汽车生成策略:

  • 自动
  • 身份
  • 序列
  • 桌子

对于 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批注才能正常工作。

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


推荐