【问题标题】:Spring Boot datasource initialization error with data.sql script after 2.5.0 upgrade2.5.0 升级后使用 data.sql 脚本的 Spring Boot 数据源初始化错误
【发布时间】:2021-05-25 20:15:37
【问题描述】:

我有一个配置了 Spring Boot 和 Spring Data JPA 的项目。

我的项目包含以下 data.sql 初始化脚本(我刚刚开始开发我的应用程序,这就是我使用嵌入式 H2 数据库的原因):

INSERT INTO Project(id, name) VALUES (1, 'Project 1');

我正在定义以下实体:

@Entity
public class Project {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    protected Project() {
    }

    public Project(String name) {
        this.name = name;
    }
    // ...
}

我没有任何其他配置/设置。

ERROR 5520 ---[  restartedMain] 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 SQL script statement #1 of URL [file:/C:/path/project/target/classes/data.sql]: INSERT INTO Project(id, name) VALUES (1, 'Project 1'); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PROJECT" not found; SQL statement:
INSERT INTO Project(id, name) VALUES (1, 'Project 1') [42102-200]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
...
Caused by: org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/C:/path/project/target/classes/data.sql]: INSERT INTO Project(id, name) VALUES (1, 'Project 1'); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PROJECT" not found; SQL statement:
INSERT INTO Project(id, name) VALUES (1, 'Project 1') [42102-200]
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:622)
    at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:254)
...
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PROJECT" not found; SQL statement:
INSERT INTO Project(id, name) VALUES (1, 'Project 1') [42102-200]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:453)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)

当然,在升级之前,应用程序启动得很好。

【问题讨论】:

    标签: spring-boot hibernate spring-data-jpa


    【解决方案1】:

    TL;DR

    似乎 Spring Boot 已经修改了它使用带有2.5.0 的 SQL 脚本初始化 DataSource 的方式。

    这可以通过在项目中包含以下属性来解决:

    spring:
      jpa:
        defer-datasource-initialization: true
    

    解释:

    2.5.0 中引入的更改中,现在似乎data.sql 脚本在 Hibernate 初始化之前执行:

    https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes#hibernate-and-datasql

    而且由于我依赖 ORM 机制(即 Hibernate)从实体定义创建架构,因此在执行初始化 SQL 脚本时数据库表不存在。

    【讨论】:

    • 所有这些答案似乎都适用于我的项目,因为我使用的是 2.6.1,但我仍然看到错误:“Table "TABLE_NAME" not found from "Error creating bean"名称为 'dataSourceScriptDatabaseInitializer'"
    • 您确定您的应用程序已配置为使用模型类@BrentFisher 创建模式吗?例如,您可以检查spring.jpa.generate-ddl 是否未设置为false,并且您可以将spring.jpa.hibernate.ddl-auto(或hibernate.hbm2ddl.auto)设置为create 以确保确定。如果这不能解决您的问题,那么您可以分享您的解决方案(也许发布一个新问题?),我可以尝试帮助您解决问题:)
    【解决方案2】:

    Add "spring.jpa.defer-datasource-initialization = true" to application.properties file.

    原因: 默认情况下,data.sql 脚本现在在 Hibernate 初始化之前运行。这使基于脚本的基本初始化行为与 Flyway 和 Liquibase 的行为保持一致。如果要使用 data.sql 填充 Hibernate 创建的模式,请将 spring.jpa.defer-datasource-initialization 设置为 true。虽然不建议混合使用数据库初始化技术,但这也允许您在通过 data.sql 填充之前使用 schema.sql 脚本来构建 Hibernate 创建的模式。

    来源: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes#hibernate-and-datasql

    【讨论】:

      【解决方案3】:

      看来你可以让ORM供应商为你创建架构,然后通过data.sql导入数据

      要实现这一点,您还需要另一个属性:spring.sql.init.mode: always

      我的全部相关属性如下:

      spring:
        sql.init.mode: always
        datasource:
          url: jdbc:postgresql://localhost:5432/products
          username: 
          password: 
        jpa:
          defer-datasource-initialization: true
          hibernate:
            ddl-auto: create-drop
          database-platform: org.hibernate.dialect.PostgreSQLDialect
      

      【讨论】:

        【解决方案4】:

        希望它对某人有所帮助。我也遇到了同样的问题,我的 data.sql 文件没有被选中,所以只有空白表 生成。我使用了下面提到的属性,它对我有用:

            spring.sql.init.mode=always
            spring.datasource.url= jdbc:mysql://${MYSQL_CONTAINER_NAME:localhost}:3306/${MYSQL_DATABASE:uber}
            spring.datasource.username=${MYSQL_USER:boca-user}
            spring.datasource.password=${MYSQL_PASSWORD:boca-password}
            spring.datasource.initialization-mode=always
            spring.jpa.show-sql=true
            spring.jpa.defer-datasource-initialization = true
            spring.jpa.hibernate.ddl-auto=update
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-16
          • 2021-09-29
          • 2017-12-18
          • 2019-11-29
          • 2020-07-08
          • 2020-04-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多