Sping Boot 2 - H2 Database - @SpringBootTest - Failing on org.h2.jdbc.JdbcSQLExcException:表已存在

csbfibhn  于 2023-04-20  发布在  Spring
关注(0)|答案(3)|浏览(158)

无法使用schema.sql创建表的脚本测试Sping Boot & H2。
所以,发生的事情是我设置了以下属性:

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.initialization-mode=always
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.platform=h2
spring.datasource.url=jdbc:h2:mem:city;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

并且,我希望使用schema.sql创建表。当我运行gradle bootRun时,应用程序工作正常。但是,当我使用gradle test运行测试时,我对Repository的测试通过,但对我的Service的测试失败,说明它正在尝试创建表,而表已经存在:
引发的异常:

Caused by: org.h2.jdbc.JdbcSQLException: Table "CITY" already exists;             
SQL statement:
CREATE TABLE city ( id BIGINT NOT NULL, country VARCHAR(255) NOT NULL, map VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, state VARCHAR(2555) NOT NULL, PRIMARY KEY (id) ) [42101-196]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.ddl.CreateTable.update(CreateTable.java:117)
at org.h2.command.CommandContainer.update(CommandContainer.java:101)
at org.h2.command.Command.executeUpdate(Command.java:260)
at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:192)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:164)
at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95)
at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:471)
... 105 more

代码已经设置好,可以重新创建场景了。

ffscu2ro

ffscu2ro1#

如果单独运行测试,它们会通过。我认为问题是由于schema.sql对同一个数据库执行了两次。第二次失败是因为表已经存在。
作为一种解决方法,您可以在application.properties中设置spring.datasource.continue-on-error=true
另一种选择是在适当的地方添加@AutoConfigureTestDatabase注解,以便为每个测试使用唯一的嵌入式数据库。

dced5bon

dced5bon2#

还有两种可能的解决方案可以尝试:
1.在创建表之前,在schema.sql中添加一个drop table if exists [tablename]
1.将语句从CREATE TABLE更改为CREATE TABLE IF NOT EXISTS

rxztt3cl

rxztt3cl3#

当数据库有名字时,它会在JVM运行时保留在内存中。这里的数据库名字是“city”:

spring.datasource.url=jdbc:h2:mem:city;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE

因此,当你想为每个测试类创建一个新的数据库时,省略数据库名称:

spring.datasource.url=jdbc:h2:mem:;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE

它被称为“内存私有”连接模式:http://www.h2database.com/html/features.html#connection_modes

相关问题