Spring Boot 存储过程中的Sping Boot MySQL数据库初始化错误

62o28rlo  于 2023-01-17  发布在  Spring
关注(0)|答案(4)|浏览(180)

在Sping 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命令也是如此。
有没有人能够在Sping Boot 中使用schema.sql文件创建MySQL存储过程?如果有,他们能举个例子吗?
有关一些其他信息,以下Spring JIRA issue解决了相同的主题,但以 Won't Fix 标签结束。

w8ntj3qf

w8ntj3qf1#

答案很简单,Sping Boot 有一个DataSource separator属性,可以在www.example.com文件中设置application.properties:

spring.datasource.separator=^;

然后,在schema.sql文件中,所有不在存储过程中的;语句都需要用新的分隔符更新。

DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()

BEGIN
  SELECT * from `database`.employees;
END ^;
zzlelutf

zzlelutf2#

添加到@Andrews回答:
在使用不是由Sping 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>
y0u0uwnf

y0u0uwnf3#

如果有人像我一样使用spring-boot + testcontainers来处理这个线程,可以省略分隔符,因为testcontainers的解析器是过程synthax的aware(尽管仍然不适用于MS-SQL)。

DROP PROCEDURE IF EXISTS `database`.FOO;
CREATE PROCEDURE `database`.FOO()

BEGIN
  SELECT * from `database`.employees;
END;
ix0qys7i

ix0qys7i4#

如果测试使用了注解,则可以执行以下操作:

@Sql(
        scripts = "/myTestSQL.sql",
        config = @SqlConfig(separator = "^;")
)
@Test
void mySQLTest() {
    // my test logic
}

假设myTestSQL.sql存储在test resources文件夹中,并且只有不同的过程或查询才需要用^;分隔,那么过程中的内容仍然需要用;分隔,就像https://stackoverflow.com/a/35871322/2092109答案中一样

相关问题