在 Spring Boot 中从文件加载 SQL 触发器
Posted
技术标签:
【中文标题】在 Spring Boot 中从文件加载 SQL 触发器【英文标题】:Load SQL Trigger from file in Spring Boot 【发布时间】:2018-02-21 19:15:58 【问题描述】:我正在尝试从资源文件夹中的 sql 文件加载自定义数据库触发器。
在我的测试课中,我添加了这个注解@Sql("classpath:custom_script.sql")
在这个文件中,我有 PostgreSQL 数据库的触发器。当我从 PgAdmin 的查询工具执行此脚本时,它们工作正常,但是当我从 Spring Boot 应用程序的测试之前加载它时,出现以下错误:
org.springframework.jdbc.datasource.init.ScriptStatementFailedException:未能执行类路径资源 [custom_script.sql] 的 SQL 脚本语句 #1:创建或替换函数 MY_TRIGGER_PROC() RETURNS TRIGGER AS $CUSTOM_TRG$ DECLARE FOO_V INTEGER;嵌套异常是 org.postgresql.util.PSQLException:未终止的美元报价开始于 SQL CREATE OR REPLACE FUNCTION MY_TRIGGER_PROC() RETURNS TRIGGER AS $CUSTOM_TRG$ DECLARE FOO_V INTEGER 中的位置 64。预计终止 $$
在 custom_script.sql 中,我有三个相关的触发器,如下所示:
CREATE OR REPLACE FUNCTION MY_TRIGGER_PROC()
RETURNS TRIGGER AS $CUSTOM_TRG$
DECLARE FOO_V INTEGER;
BEGIN
SELECT COUNT(F.ID)
INTO FOO_V
FROM FOO_TABLE F;
IF FOO_V > 0
THEN
RAISE EXCEPTION 'CUSTOM EXCEPTION ERROR MESSAGE FOR ID ', NEW.ID
USING ERRCODE = 'restrict_violation';
END IF;
RETURN NEW;
END;
$CUSTOM_TRG$
LANGUAGE plpgsql;
CREATE TRIGGER CUSTOM_TRG
BEFORE INSERT
ON FOO_TABLE
FOR EACH ROW
EXECUTE PROCEDURE MY_TRIGGER_PROC();
我预计错误是由于分隔符或多行问题,所以我将这些属性添加到属性文件中:
spring.jpa.properties.hibernate.connection.charSet=UTF-8
spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor=org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
spring.datasource.separator=^;
还可以编辑我的脚本,如下面的代码所示,但它没有帮助。你能帮我解决这个问题吗?谢谢。
编辑脚本:
CREATE OR REPLACE FUNCTION MY_TRIGGER_PROC()
RETURNS TRIGGER AS $CUSTOM_TRG$
DECLARE FOO_V INTEGER;
BEGIN
SELECT COUNT(F.ID)
INTO FOO_V
FROM FOO_TABLE F;
IF FOO_V > 0
THEN
RAISE EXCEPTION 'CUSTOM EXCEPTION ERROR MESSAGE FOR ID ', NEW.ID
USING ERRCODE = 'restrict_violation';
END IF;
RETURN NEW;
END;
$CUSTOM_TRG$
LANGUAGE plpgsql^;
CREATE TRIGGER CUSTOM_TRG
BEFORE INSERT
ON FOO_TABLE
FOR EACH ROW
EXECUTE PROCEDURE MY_TRIGGER_PROC()^;
【问题讨论】:
【参考方案1】:一种解决方案是在函数定义周围使用单引号,而不是这里使用的 $CUSTOM_TRG$;在类似的情况下,应该再次抛弃 $$ 美元报价,转而使用简单的单引号。但是,整个定义的单引号需要在函数定义中转义引号,如 Postgresql 文档中所述:
使用美元引号(参见第 4.1.2.4 节)来编写函数定义字符串通常很有帮助,而不是普通的单引号语法。如果没有美元引号,函数定义中的任何单引号或反斜杠都必须通过加倍来转义。
因此,在您的示例中,您需要将函数定义中的单引号加倍,发生在 FOO_V > 0 的逻辑中。
【讨论】:
以上是关于在 Spring Boot 中从文件加载 SQL 触发器的主要内容,如果未能解决你的问题,请参考以下文章
在 Eclipse 中从 Spring:boot 项目创建 war 文件
在 Spring Boot 中从命令行设置活动配置文件和配置位置
尝试在 Java Spring Boot 中从 H2 数据库中获取相关实体