Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot datasource initialization error with data.sql script after 2.5.0 upgrade

I have a project configured with Spring Boot and Spring Data JPA.

My project contains the following data.sql initialization script (I'm just starting developing my application that's why I use an embedded H2 database):

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

And I'm defining the following entity:

@Entity
public class Project {

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

    private String name;

    protected Project() {
    }

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

I don't have any other configuration/setup in place.

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)

Of course, before the upgrade, the application was starting just fine.

like image 973
Gerardo Roza Avatar asked May 25 '21 20:05

Gerardo Roza


2 Answers

TL;DR

It seems Spring Boot has modified how it initializes the DataSource with SQL scripts with 2.5.0.

This can be fixed by including the following property in the project:

spring:
  jpa:
    defer-datasource-initialization: true

The explanation:

Among the changes introduced in 2.5.0, it seems now the data.sql script is executed before Hibernate is initialized:

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

And since I'm relying on the ORM mechanism (i.e. Hibernate) to create the schema from the entity definition, the database table does not exist at the moment the initialization SQL script is executed.

like image 180
Gerardo Roza Avatar answered Nov 09 '22 04:11

Gerardo Roza


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

Reason: By default, data.sql scripts are now run before Hibernate is initialized. This aligns the behavior of basic script-based initialization with that of Flyway and Liquibase. If you want to use data.sql to populate a schema created by Hibernate, set spring.jpa.defer-datasource-initialization to true. While mixing database initialization technologies is not recommended, this will also allow you to use a schema.sql script to build upon a Hibernate-created schema before it’s populated via data.sql.

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

like image 5
Vikas Reddy Avatar answered Nov 09 '22 04:11

Vikas Reddy