带有存储过程的 Spring Boot MySQL 数据库初始化错误
Posted
技术标签:
【中文标题】带有存储过程的 Spring Boot MySQL 数据库初始化错误【英文标题】:Spring Boot MySQL Database Initialization Error with Stored Procedures 【发布时间】:2016-06-21 18:22:13 【问题描述】:在 Spring Boot 应用程序中,我尝试在运行集成测试之前初始化一些 mysql 数据库表和存储过程,方法是按照documentation 中的建议将 schema.sql 文件放在我的资源目录中。
create table 语句有效,但 create procedure 语句引发异常。导致异常的示例 schema.sql 文件语句如下所示:
DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()
BEGIN
SELECT * from `database`.employees;
END;
问题是存储过程中的 ;
字符被 Spring ScriptUtils 类解析出来,该类在执行前解析 schema.sql 文件,这会导致 MySQL 在脚本上抛出语法错误.
我查看了ScriptUtils 类,但无法找到一种方法来使用程序转义;
字符。使用\\
和\
作为转义字符也不起作用,MySQL 的DELIMITER
命令也是如此。
有没有人能够通过 Spring Boot 使用 schema.sql 文件创建 MySQL 存储过程?如果可以,他们可以举个例子吗?
有关其他信息,以下Spring JIRA issue 解决了相同的主题,但以 Won't Fix 标签结束。
【问题讨论】:
我没有太多信息,但可以试试^
作为转义字符。
【参考方案1】:
答案很简单。 Spring Boot 有一个 DataSource 分隔符属性,可以在 application.properties 文件中设置:
spring.datasource.separator=^;
然后在 schema.sql 文件中所有不在存储过程中的;
语句都需要使用新的分隔符进行更新。
DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()
BEGIN
SELECT * from `database`.employees;
END ^;
【讨论】:
不要错过分隔符中的分号 (^;)【参考方案2】:添加到@Andrews 答案:
使用 Spring Boot 未自动创建的自定义 dataSource
时,可能会发生未使用 spring.datasource.separator
属性的情况。在这种情况下,分隔符不会转发到Populator
。这种情况下可以直接在数据源初始化中设置。例如,假设 dataSource
在别处定义,则可以在特殊更新配置文件中使用以下内容:
<jdbc:initialize-database data-source="dataSource" enabled="$initDatabase:false" separator="^;">
<jdbc:script location="$update.schema.script" />
</jdbc:initialize-database>
或者,当显式声明填充器时:
<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>
【讨论】:
【参考方案3】:如果有人像我一样使用 spring-boot + testcontainers 进入这个线程,可以省略分隔符,因为 testcontainers 的解析器是程序 synthax 的aware(尽管仍然不适用于 MS-SQL)。所以原始脚本可以工作:
DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()
BEGIN
SELECT * from `database`.employees;
END;
【讨论】:
以上是关于带有存储过程的 Spring Boot MySQL 数据库初始化错误的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot - MySQL 到 Postgres 的迁移
Spring boot(带有 jpa 的 mysql):没有名为“entityManagerFactory”的 bean 可用
使用带有 LIKE 的 mysql 本机查询的 spring boot 搜索返回空
Spring Boot集成 MyBatis 操作 MySQL 8