Spring Boot 2.5.0、Spring Cloud 2020.0.2 和 Hibernate 5.4.31 - H2 数据库多行插入失败
Posted
技术标签:
【中文标题】Spring Boot 2.5.0、Spring Cloud 2020.0.2 和 Hibernate 5.4.31 - H2 数据库多行插入失败【英文标题】:Spring Boot 2.5.0, Spring Cloud 2020.0.2 and Hibernate 5.4.31 - H2 Database Multi Row Insert Failing 【发布时间】:2021-08-11 11:56:38 【问题描述】:在使用 SB 版本 2.5.0、Spring Cloud 处理 Spring Boot 应用程序时(适用于 Centralized Config 2020.0.2) Hibernate 版本是 5.4.31(我没有使用特定的 Hibernate 版本,它符合 Spring Boot 兼容性)。 使用 H2 数据库存储内存数据,因为我需要创建示例应用程序进行演示。
在 Resources 文件夹中,我确实有我的 SQL 文件。
当我将其命名为data.sql
时,应用程序根本没有启动。
当我将此文件重命名为 import.sql
时,我的应用程序已启动,但仍面临多行插入问题。
数据插入 SQL 文件
/* Data for Entity DataTable */
INSERT INTO data_table (name) VALUES
('Data 1'),
('Data 2'),
('Data 3');
当我的应用程序使用 Spring Boot 2.3.10.RELEASE 和 Spring Cloud Hoxton.SR5 运行时,这工作得非常好。
我也尝试过 JPA 和 Hibernate 的属性来解决这个问题,但仍然没有成功。查找我使用的属性如下:
spring.jpa.properties.hibernate.jdbc.batch_size=20
spring.jpa.properties.hibernate.order_inserts=true
由于更新了 Spring Boot 和 Spring Cloud 版本,我不确定是否需要特别设置 H2 数据库以用于多行插入。
看起来与 Hibernate 或 H2 数据库问题有关。
WARN 7952 --- [ main] o.h.t.s.i.ExceptionHand lerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL "('Data 2')" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "('Data 2')" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.4.31.Final.jar!/:5.4.31.Final]
...
...
...
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "('Data 2'[*]),"; expected "(, WITH, SELECT, TABLE, VALUES"; SQL statement: ('Data 2'), [42001-200]
更新
我已将我的 SQL 文件名恢复为 data.sql,然后我观察到相同的 H2 数据库异常即将到来,并且应用程序无法启动。
在下面找到我得到的启动执行的详细信息:
WARN 4720 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException:
Failed to execute SQL script statement #1 of URL [jar:file:/D:/Projects/SpringCloudDemoApp/spring-cloud-demo/target/demo-data-service-0.1.jar!/BOOT-INF/classes!/data.sql]: INSERT INTO data_table (name) VALUES ('Data 1'), ('Data 2'), ('Data 3'); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "DATA_TABLE" not found; SQL statement: INSERT INTO data_table (name) VALUES ('Data 1'), ('Data 2'), ('Data 3') [42102-200]
...
...
ERROR 4720 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQLscript statement #1 of URL [jar:file:/D:/Projects/SpringCloudDemoApp/spring-cloud-demo/target/demo-data-service-0.1.jar!/BOOT-INF/classes!/data.sql]: INSERT INTO data_table (name) VALUES ('Data 1'), ('Data 2'), ('Data 3'); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "DATA_TABLE" not found; SQL statement: INSERT INTO data_table (name) VALUES ('Data 1'), ('Data 2'), ('Data 3') [42102-200]
另外请查找我的 Entity 类,以防万一出现问题,但不要认为 Entity 类有什么问题,因为它适用于较旧的 Spring Boot 和 Spring Cloud 版本,但仍在这里分享。
数据表实体类
@Entity
@Table(name = "data_table")
public class DataTable
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "dataid")
private Long id;
@Column(name = "name", nullable = false, unique = true, length = 200)
private String name;
// Getter Setters will follow here
应用 YML 文件
server:
port: 9090
spring:
datasource:
url: jdbc:h2:mem:demodb
driverClassName: org.h2.Driver
username: scdemo
password: scdemopass
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
jdbc:
batch_size: 20
order_inserts: true
h2:
console:
enabled: true
path: /h2-console
settings:
trace: false
重要更新
我也尝试了相同的方法,仅使用 Spring Boot 2.5.0 和 JPA,使用 H2 数据库的 Hibernate,创建了一个示例应用程序,它只有 4 个文件,要启动的 Spring Boot 应用程序文件和实体类 data.sql
为上面,以及用于配置的application.yml
,并确保它在相同条件下失败。我确认我在从 data.sql
加载数据以插入时遇到了同样的错误,这适用于较旧的 Spring Boot 版本。
我刚刚将 SB 版本从 2.5.0
更新为 2.3.10.RELEASE
,并且相同的代码可以正常工作。
更多详情:
当data.sql
文件与 Spring Boot 版本2.3.10.RELEASE
一起使用时,data.sql
文件中的插入语句是多行且位于多行的。它工作得很好。
当data.sql
重命名为import.sql
时,Spring Boot 版本为 2.5.0,import.sql
文件中的插入语句是多行的,但预计将所有值保持在同一行,这也效果很好。
当data.sql
重命名为import.sql
,Spring Boot 版本为2.5.0
并且import.sql
文件中的插入语句是多行且位于多行时,此方案将失败。因为它将每个新行上的语句视为 DDL。在这种情况下,应用程序运行,但数据插入不发生。
GenerationTarget encountered exception accepting command : Error executing DDL "('Data 3')" via JDBC Statement
第 4 种情况是 data.sql
与 Spring Boot 版本 2.5.0
和 data.sql
文件中的插入语句是多行并且在多行上,这种情况也失败了在数据源初始化时和应用程序根本不运行。
分享相同的示例代码: 源代码可以在上面提到的4个条件下尝试: demo-data-service
请提出建议。
【问题讨论】:
有什么问题?插入如何失败? 添加了错误详细信息,这可能会提供一些线索,说明问题出在哪里。我意识到这个问题似乎与 Hibernate 版本或 H2 DB 有关。但不确定,在我更新 Spring Boot 和 Spring Cloud 版本之前,Multi-Row insert 工作正常。 能否将其重命名为 data.sql 并将其放置在 src/main/resources 中,然后再试一次,如果它不起作用,您能否报告启动异常?import.sql
由 Hibernate 处理,而不是 Spring Boot。你能分享你在某个地方的示例应用程序,以便我们自己运行吗?
Spring Boot 2.5.0 尝试在应用数据库模式之前运行 data.sql。我必须恢复到 2.4.6 才能正常工作。
【参考方案1】:
您需要将此添加到应用配置中:
spring.jpa.defer-datasource-initialization=true
自 Spring Boot 2.5.0 起,data.sql 默认在 schema 初始化之前执行。
另见:
Spring Boot Data JPA with H2 and data.sql - Table not Found
【讨论】:
真棒@Dan。您在下移到版本2.4.6
的问题中添加的评论以及在此处添加此属性以及版本2.5.0
的答案,这两种解决方案对我来说都很好。非常感谢。
为了从 Spring 中获取更多详细信息,我在 spring 文档中搜索了这个属性并找到了详细信息,所以在这里分享链接 howto data-initialization using-basic-sql-scripts【参考方案2】:
我发现自己在使用 Spring boot 2.5.0 时无法在表名后添加换行符。
使用 Spring Boot 2.5.0,导入脚本应命名为 import.sql
所以,这会引发异常
INSERT into
TRANSACTIONS (id, account_id, amount, currency, type) VALUES (5, 2, -10.00, 'GBP', 'MONEY_TRANSFER')
虽然没有
INSERT into TRANSACTIONS (id, account_id, amount, currency, type) VALUES (5, 2, -10.00, 'GBP', 'MONEY_TRANSFER')```
【讨论】:
以上是关于Spring Boot 2.5.0、Spring Cloud 2020.0.2 和 Hibernate 5.4.31 - H2 数据库多行插入失败的主要内容,如果未能解决你的问题,请参考以下文章
全网最新 pig 2.5.0发布 !支持Spring Boot 2.2 和 Spring Cloud Hoxton
Spring Boot 2.5.0 重新设计的spring.sql.init 配置有啥用?
Spring Boot 2.5.0 重新设计的spring.sql.init 配置有啥用?
Spring Boot 2.5.0正式版发布,MateCloud微服务平台同步升级