使用 GenerationType.AUTO 的 h2 测试找不到序列“HIBERNATE_SEQUENCE”

yur*_*s87 4 java hibernate h2 spring-boot

我正在尝试将我们的一项服务迁移到 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)
Run Code Online (Sandbox Code Playgroud)

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

@GeneratedValue(strategy = GenerationType.AUTO)
Run Code Online (Sandbox Code Playgroud)

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

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

    OrderDetails findFirstByOrderIdOrderByIdDesc(String orderId);
}
Run Code Online (Sandbox Code Playgroud)

这里可能出现什么问题?

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

per*_*oro 8

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

CREATE TABLE CUSTOMER(
  id int primary key,
);

CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 1 INCREMENT BY 1;
Run Code Online (Sandbox Code Playgroud)

我建议使用GenerationType.SEQUENCE并尝试使用您的自定义数据库序列重新创建您的 id 模式。您可以在此处阅读有关 GenerationType 的更多信息


Kus*_*aha 6

我在使用 h2 编写 spring boot 示例代码时遇到了同样的问题。请在下面查看我的发现的详细信息。在您的实体类序列中没有给出并检查您的表,即您是否为主键指定了 AUTO_INCRMENT ?

请按照以下方式操作。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
);
Run Code Online (Sandbox Code Playgroud)
  1. 检查您的实体类并更新主键,如下所示

    公共类员工{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,GenerationType 被赋予 IDENTITY,您也可以赋予 AUTO。另外,如果您使用 h2 内存数据库并且表在启动时插入了一些记录(如果 dml 文件在资源中可用),那么休眠插入可能会给出唯一的约束,因为序列 1,2,3..(取决于插入的记录数) whilestartup)可能已经使用过,正如我上面所说,hibernate将从1开始生成序列,并且对于每个新插入都会增加1。所以我建议不要在引导启动时插入记录,最好以编程方式插入。
    为了您的学习,您可以使用上面给出的方法,但如果它可以在生产中使用,那么最好实现您自己的逻辑来生成序列。