Spring Boot MySQL Database Initialization Error with Stored Procedures
The answer turned out to be very simple. Spring Boot has a DataSource separator property that can be set in the application.properties file:
spring.datasource.separator=^;
Then in the schema.sql file all ;
statements not within the stored procedure need to be updated with the new separator.
DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()
BEGIN
SELECT * from `database`.employees;
END ^;
Adding to @Andrews answer:
When using a custom dataSource
that is not automatically created by Spring Boot, it can happen that the spring.datasource.separator
property is not used. In this cases the separator is not forwarded to the Populator
. In this case it can be set directly in the data source initialization. For example, the following can be used in a special update profile assuming dataSource
is defined elsewhere:
<jdbc:initialize-database data-source="dataSource" enabled="${initDatabase:false}" separator="^;">
<jdbc:script location="${update.schema.script}" />
</jdbc:initialize-database>
Or, when the the populator is explicitly stated:
<bean id="dbPopulator" class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator">
<property name="separator" value="^;"/>
<property name="scripts">
<list>
<value>${update.schema.script}</value>
</list>
</property>
</bean>
<bean id="initDatabase" class="org.springframework.jdbc.datasource.init.DataSourceInitializer">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="databasePopulator">
<ref bean="dbPopulator"/>
</property>
<!-- The same can be done for the cleaner: -->
<!-- <property name="databaseCleaner"><ref bean="dbCleanup"/></property> -->
</bean>
In case someone steps on this thread using spring-boot + testcontainers as I did, one can just omit separators, cause testcontainers' parser is aware of procedures synthax (although still doesn't work for MS-SQL). So original script will work:
DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()
BEGIN
SELECT * from `database`.employees;
END;