在GenerationType.AUTO的h2测试中找不到序列“ HIBERNATE_SEQUENCE”

时间:2018-08-03 14:20:43

标签: java hibernate spring-boot h2

我正在尝试将我们的一项服务迁移到Spring Boot 2.0.3。 尽管大多数测试都可以,但是其中一项失败并显示错误:

Caused by: org.h2.jdbc.JdbcSQLException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-197]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
    at org.h2.message.DbException.get(DbException.java:179)
    at org.h2.message.DbException.get(DbException.java:155)
    at org.h2.command.Parser.readSequence(Parser.java:5970)
    at org.h2.command.Parser.readTerm(Parser.java:3131)
    at org.h2.command.Parser.readFactor(Parser.java:2587)

这确实令人困惑,因为所有实体都依赖于相同的世代ID机制:

@GeneratedValue(strategy = GenerationType.AUTO)

这是一个存储库测试,存储库本身非常简单:

@Repository
public interface OrderDetailsRepository extends JpaRepository<OrderDetails, Long> {

    OrderDetails findFirstByOrderIdOrderByIdDesc(String orderId);
}

这里可能出什么毛病?

PS:,是的,实体中同时存在orderIdId字段。

3 个答案:

答案 0 :(得分:3)

选择@GeneratedValue(strategy = GenerationType.AUTO)时,Hibernate将基于特定于数据库的方言选择一种生成策略。 您遇到的问题是休眠状态无法找到HIBERNATE_SEQUENCE,因此无法为该序列创建新对象。尝试添加这样的序列,它应该可以解决问题,但可能导致数据不一致...

CREATE TABLE CUSTOMER(
  id int primary key,
);

CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 1 INCREMENT BY 1;

我建议您使用GenerationType.SEQUENCE,然后尝试使用自定义数据库序列重新创建ID模式。您可以阅读有关GenerationType的更多信息 here

答案 1 :(得分:1)

用h2编写用于Spring Boot的示例代码时遇到了相同的问题。请在下面找到我的发现的细节。 在您的实体类序列中没有给出并检查您的表,即您是否给定AUTO_INCREMENT作为主键?

请按照以下说明进行操作。 1.一次检查您的ddl并将主键设置为auto_increment(有关ID,请参见下文)

    CREATE TABLE EMPLOYEES (
  id INT AUTO_INCREMENT  PRIMARY KEY,
  first_name VARCHAR(250),
  last_name VARCHAR(250),
  email VARCHAR(250) DEFAULT NULL
);
  1. 检查您的实体类并更新主键,如下所示

    公共类员工{

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

    请注意,GenerationType被赋予IDENTITY,您也可以赋予AUTO。另外,如果您使用的是h2内存数据库,并且在启动启动时插入了很少的表记录(如果dml文件在资源中可用),则休眠插入可能会给出唯一的约束,因为序列1,2,3 ..(取决于插入的记录数)就像我在上面说过的那样,冬眠会从1生成序列,并且每次新插入都会加1。因此,我建议不要在引导启动时插入记录,而最好以编程方式插入。
    为了您的学习,您可以使用上面给出的方法,但是如果可以在生产中使用,则最好实现自己的逻辑以生成序列。

答案 2 :(得分:1)

我有类似的问题。如果我理解正确,它就会像这样下去。

在Spring升级之前,我使用AUTO-但实际上默认情况下选择了IDENTITY策略。我有如下定义的自动递增PK:

id            BIGINT AUTO_INCREMENT PRIMARY KEY

一切都很好。

在春季升级中,我必须指定H2方言:

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

我读到,如果您使用Hibernate作为持久性提供程序,它将基于数据库特定的方言选择一种生成策略。对于H2,它可能选择了全局序列(根据JPA规范,这就是AUTO的意思)-并且找不到序列。 解决方案当然是创建序列(如上所述),或手动替代原来自动选择的IDENTITY。

CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 1 INCREMENT BY 1;

@GeneratedValue(strategy = GenerationType.IDENTITY)

我认为根本原因是在时间上AUTO的含义不明确/定义不清/理解不正确。可能原来从“自动”切换到IDENTITY基本上是一个错误。