使用 GenerationType.AUTO 的 h2 测试未找到序列“HIBERNATE_SEQUENCE”
Posted
技术标签:
【中文标题】使用 GenerationType.AUTO 的 h2 测试未找到序列“HIBERNATE_SEQUENCE”【英文标题】:Sequence "HIBERNATE_SEQUENCE" not found for h2 test with GenerationType.AUTO 【发布时间】:2019-01-11 11:14:41 【问题描述】:我正在尝试将我们的一项服务迁移到 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:而且,是的,实体中同时存在 orderId
和 Id
字段。
【问题讨论】:
如果换成 GenerationType.IDENTITY 会发生什么?我在这方面比 AUTO 和休眠更幸运。虽然两者都应该可以正常工作。 它解决了问题,但对于其余实体来说它是自动的,我希望它们保持一致。 也许您可以全面更改政策? 嗯,我可以做到,但我有点想弄清楚为什么它在一个地方失败而另一个地方失败。 是的,很公平。 thoughts-on-java.org/jpa-generate-primary-keys ***.com/questions/39807483/… 我认为这些链接提供了一些见解。 【参考方案1】:当您选择@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
【讨论】:
【参考方案2】:我在使用 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
);
检查您的实体类并更新主键,如下所示
公共类员工
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
请注意,GenerationType 被赋予 IDENTITY,您也可以赋予 AUTO。此外,如果您在引导启动时使用 h2 内存数据库和表插入了几条记录(如果 dml 文件在资源中可用),那么休眠插入可能会给出唯一约束,因为序列 1、2、3 ..(取决于插入的记录数while startup) 可能已经使用过,正如我上面所说,hibernate 将从 1 生成序列,并且每次新插入都会增加 1。所以我建议不要在启动时插入记录,最好以编程方式插入。 为了您的学习,您可以使用上面给出的方法,但如果它可以在生产中使用,那么最好实现您自己的逻辑来生成序列。
【讨论】:
感谢提及spring.jpa.hibernate.ddl-auto 我没查。【参考方案3】:我有类似的问题。如果我理解正确的话就这样下去了。
在 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 基本上是一个错误。
【讨论】:
以上是关于使用 GenerationType.AUTO 的 h2 测试未找到序列“HIBERNATE_SEQUENCE”的主要内容,如果未能解决你的问题,请参考以下文章
如何使用JPA GenerationType.AUTO提供初始值或增量ID
使用 GenerationType.AUTO 的 h2 测试未找到序列“HIBERNATE_SEQUENCE”
如何在MySQL中保存数据并将@Id从GenerationType.AUTO更改为GenerationType.TABLE
@GeneratedValue(strategy = GenerationType.AUTO) 没有像想象的那样工作
Spring/Hibernate GenerationType.AUTO 的数据库备份问题
如何让 Hibernate 在 Oracle 上将 SequenceHiLoGenerator 用于 JPA GenerationType.AUTO?