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
在使用 SB 2.5.0 版 Spring 启动应用程序时,Spring 云(用于集中配置 2020.0.2)
Hibernate 版本是 5.4.31(我没有使用特定的 Hibernate 版本,它是根据 Spring 启动兼容性)。
使用 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 引导和 Spring 云版本,我不确定是否有什么特别需要设置 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]
另外请找到我的实体 class 以防出现问题,但不要认为实体 class 有任何问题,因为它适用于较旧的 Spring 引导和Spring 云版本,但仍然在这里分享。
数据表实体Class
@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,Hibernate with H2 Database,创建了一个只有 4 个文件的示例应用程序,Spring Boot Application 文件到启动和实体 class、data.sql
如上所述,以及 application.yml
用于配置,并确保它在相同条件下失败。我确认我在从 data.sql
加载数据以插入时遇到相同的错误,这适用于较旧的 Spring 引导版本。
我刚刚将 SB 版本从 2.5.0
更新到 2.3.10.RELEASE
,同样的代码也能正常工作。
更多详情:
当data.sql
文件与Spring引导版本2.3.10.RELEASE
一起使用时,data.sql
文件中的Insert语句是多行和在多条线上。它工作得很好。
当data.sql
重命名为import.sql
时,与Spring引导版本2.5.0和import.sql
文件中的Insert Statements是多-row 但希望将所有值保持在同一行,这也很有效。
当 data.sql
重命名为 import.sql
时,Spring 引导版本 2.5.0
和 import.sql
文件中的插入语句是多行并且在多行上,这种情况失败。因为它将每个新行上的语句视为 DDL。在这种情况下,应用程序运行但数据插入不会发生。
GenerationTarget encountered exception accepting command : Error executing DDL "('Data 3')" via JDBC Statement
而第 4 种情况是 data.sql
与 Spring 引导版本 2.5.0
和 data.sql
文件中的插入语句是多行的并且在多行上,这种情况也失败了在数据源初始化和应用程序时根本没有运行。
分享相同的示例代码:
满足上述4个条件可以尝试源码:
demo-data-service
求推荐。
您需要将此添加到应用配置中:
spring.jpa.defer-datasource-initialization=true
自 Spring Boot 2.5.0 起,data.sql 默认在架构初始化之前执行。
另请参阅:
我发现自己使用 Spring boot 2.5.0 时无法在 table 名称后添加换行符。
使用 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')```
在使用 SB 2.5.0 版 Spring 启动应用程序时,Spring 云(用于集中配置 2020.0.2) Hibernate 版本是 5.4.31(我没有使用特定的 Hibernate 版本,它是根据 Spring 启动兼容性)。 使用 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 引导和 Spring 云版本,我不确定是否有什么特别需要设置 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]
另外请找到我的实体 class 以防出现问题,但不要认为实体 class 有任何问题,因为它适用于较旧的 Spring 引导和Spring 云版本,但仍然在这里分享。
数据表实体Class
@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,Hibernate with H2 Database,创建了一个只有 4 个文件的示例应用程序,Spring Boot Application 文件到启动和实体 class、data.sql
如上所述,以及 application.yml
用于配置,并确保它在相同条件下失败。我确认我在从 data.sql
加载数据以插入时遇到相同的错误,这适用于较旧的 Spring 引导版本。
我刚刚将 SB 版本从 2.5.0
更新到 2.3.10.RELEASE
,同样的代码也能正常工作。
更多详情:
当
data.sql
文件与Spring引导版本2.3.10.RELEASE
一起使用时,data.sql
文件中的Insert语句是多行和在多条线上。它工作得很好。当
data.sql
重命名为import.sql
时,与Spring引导版本2.5.0和import.sql
文件中的Insert Statements是多-row 但希望将所有值保持在同一行,这也很有效。当
data.sql
重命名为import.sql
时,Spring 引导版本2.5.0
和import.sql
文件中的插入语句是多行并且在多行上,这种情况失败。因为它将每个新行上的语句视为 DDL。在这种情况下,应用程序运行但数据插入不会发生。GenerationTarget encountered exception accepting command : Error executing DDL "('Data 3')" via JDBC Statement
而第 4 种情况是
data.sql
与 Spring 引导版本2.5.0
和data.sql
文件中的插入语句是多行的并且在多行上,这种情况也失败了在数据源初始化和应用程序时根本没有运行。
分享相同的示例代码: 满足上述4个条件可以尝试源码: demo-data-service
求推荐。
您需要将此添加到应用配置中:
spring.jpa.defer-datasource-initialization=true
自 Spring Boot 2.5.0 起,data.sql 默认在架构初始化之前执行。
另请参阅:
我发现自己使用 Spring boot 2.5.0 时无法在 table 名称后添加换行符。
使用 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')```