Exception “org.h2.jdbc.JdbcSQLSyntaxErrorException:Table “NAME” not found” 在初始化 H2 数据库以测试 Spring Boot 应用程序时

问题描述 投票:0回答:2

我编写了带有@SpringBootTest 注释的集成测试。为了运行测试,我将数据从测试资源中的 data.sql 插入到 H2 数据库。

我有一种情况,第一次测试成功运行,多次后,我有一个错误,它告诉我,H2 无法在表中插入数据,因为找不到该表。每次下一次启动测试时,都会出现不同的原始错误。在同一个日志中,我看到在异常发生之前创建了这个表并且其他插入操作成功执行。我看到我的 5 个测试中有 4 个是绿色的,一个是红色的。它可以在不同的时间进行不同的测试。

IDE 的重启使测试再次成功运行 3-4 次。之后,错误返回。

我尝试在我的测试类和测试方法中使用@DirtiesContext(),但它并没有解决问题。

我猜测问题的根源可能是我初始化数据库的方式。对于这两个数据库,我都使用一个 data.sql 文件的引用。我没能找到一种方法将它们分成不同的 *.sql 文件。

第二个猜测是在创建表之前开始插入数据库。我现在通过将所有插入移动到测试代码中来检查这个理论。但是我不确定它是否会有所帮助,因为我播种记录表是在插入开始之前创建的。

我在每次测试运行前都使用“mvn clean”。

我将非常感谢您在解决此问题方面的建议。

我的实体:

@Entity
@Table(name = "entity1", schema = "schema1")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SomeEntityClass extends GenericEntity<Long> { ...}


@MappedSuperclass
public abstract class GenericEntity<ID extends Serializable> implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column

    protected ID id;

//getter, setter
}

在我的 data.sql 文件中初始化如下所示:

create schema if not exists schema1;
create schema if not exists schema2; 

drop table if exists schema1.table1;
create table schema1.table1
(....structure of the table...)
 
drop table if exists schema2.table2;
create table schema2.table2
(....structure of the table...)
 
INSERT INTO schema1.table1
(...)
VALUES (...)
 
... many insertions
 
 
INSERT INTO schema2.table2
(...)
VALUES (...)
 
... many insertions

这是application.properties中的H2配置,在test/resources中:

# The first database
spring.datasource.url=jdbc:h2:mem:database01;INIT=RUNSCRIPT FROM 'src/test/resources/data.sql'
spring.datasource.username=user1
spring.datasource.password=abc
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.generate-ddl=true

# The second database
spring.datasource.security.url=\
  jdbc:h2:mem:dbo_security_db:database02;INIT=RUNSCRIPT FROM 'src/test/resources/data.sql'
spring.datasource.security.username=user1
spring.datasource.security.password=abc
spring.datasource.security.driver-class-name=org.h2.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true

错误日志:

08-09-2021 09:00:08.729 DEBUG [o.s.jdbc.datasource.init.ScriptUtils] - 0 returned as update count for SQL: create table schema1.table1( ….)
08-09-2021 09:00:08.730 DEBUG [o.s.jdbc.datasource.init.ScriptUtils] - 1 returned as update count for SQL: INSERT INTO schema1.table1(...) VALUES ()
///...other insertions into this table performed well
08-09-2021 09:00:08.735 WARN  [o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext] - 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 #36 of URL [file:/home/nikiforov-java/Documents/.../target/test-classes/data.sql]: INSERT INTO schema1.table1(...) VALUES (...); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "TABLE1" not found; SQL statement: ...

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
08-09-2021 09:00:08.782 ERROR [o.s.boot.SpringApplication] - Application run failed

spring-boot spring-data-jpa h2 spring-jdbc spring-boot-test
2个回答
4
投票

将此属性添加到

application.properties

spring.jpa.defer-datasource-initialization=true

根据Spring Boot 2.5 RELEASE notes

默认情况下,

data.sql
脚本现在在 Hibernate 初始化之前运行。这使基于脚本的基本初始化行为与 Flyway 和 Liquibase 的行为保持一致。如果要使用
data.sql
填充 Hibernate 创建的模式,请将
spring.jpa.defer-datasource-initialization
设置为
true
.


0
投票

添加后:

spring.jpa.defer-datasource-initialization=true

到你的 application.properties 文件,如果你仍然有相同的:

"Exception "org.h2.jdbc.JdbcSQLSyntaxErrorException:Table "NAME" not found
例外, 仔细检查实体中的所有列名。 确保您没有使用保留关键字,如果使用了,请使用以下方法添加别名:
@Column(name = "<YOUR NOT RESERVED KEYWORD COLUMN NAME>")

© www.soinside.com 2019 - 2024. All rights reserved.