Spring 启动数据库初始化触发器的 MySQLException

Spring Boot Database initialization MySQLException for Trigger

我正在使用 Spring 引导数据库初始化使用 Spring JDBC 和 schema.sql file.I 我正在使用 MYSQL

如果我在 schema.sql 中有简单的 table 创建,如下所示,它工作正常

CREATE TABLE Persons
(
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);

但是当我如下添加一个触发器时,它在 MySQL Workbench

中正确运行
DROP TRIGGER IF EXISTS Persons_log_update; 

CREATE TRIGGER Persons_log_update 
    BEFORE UPDATE ON Persons
    FOR EACH ROW 
BEGIN

    INSERT INTO Personshistory(PersonID,LastName,FirstName,Address,City)
    values(OLD.PersonID,OLD.LastName,OLD.FirstName,OLD.Address,OLD.City);

END ^;

我用过spring.datasource.separator=^;在属性文件中提到

但它失败了,因为

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TRIGGER Persons_log_update BEFORE UPDATE ON Persons FOR EACH ROW BE' at line 1

我想我的问题与 问题相同,但那是在 postgresql 中。

编辑: 如果我删除 spring.datasource.separator=^;来自属性文件并在光标下方

DROP TRIGGER IF EXISTS Persons_log_update; 

DELIMITER $$
CREATE TRIGGER Persons_log_update 
    BEFORE UPDATE ON Persons
    FOR EACH ROW 
BEGIN

    INSERT INTO Personshistory(PersonID,LastName,FirstName,Address,City)
    values(OLD.PersonID,OLD.LastName,OLD.FirstName,OLD.Address,OLD.City);

END$$
DELIMITER ;

它给出同样的错误

 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER $$ CREATE TRIGGER Persons_log_update BEFORE UPDATE ON Persons FO' at line 1

当我在 application.properties 中添加 spring.datasource.separator=^; 并且 procedure/trigger 之外的每一行都应以 ^; 终止时,我的问题得到了解决 示例如下:

DROP TRIGGER IF EXISTS Persons_log_update ^; 

CREATE TRIGGER Persons_log_update 
    BEFORE UPDATE ON Persons
    FOR EACH ROW 
BEGIN

    INSERT INTO Personshistory(PersonID,LastName,FirstName,Address,City)
    values(OLD.PersonID,OLD.LastName,OLD.FirstName,OLD.Address,OLD.City);

END ^;

设置spring.datasource.separator=^;没有解决我的问题。

我正在使用 ResourceDatabasePopulator class 加载 sql 脚本,发现此 class 提供了设置分隔符的方法,所以我这样做了。

注意:dataSource 对象是自动装配的,由 spring 配置。所以在使用它之前添加它(javax.sql.DataSource)。

@Autowired DataSoruce 数据源

ResourceDatabasePopulator triggersPopulator = new ResourceDatabasePopulator(false, false, StandardCharsets.UTF_8.toString(), new ClassPathResource("triggers.sql"));
        triggersPopulator.setSeparator("//");
        triggersPopulator.execute(dataSource);

并根据分隔符 (//) 在 sql 脚本中完成更改。

drop trigger if exists news_data_total_news_incremental_trigger;
//
create trigger news_data_total_news_incremental_trigger
after insert on `news_data` for each row
begin
declare cnt,newcnt bigint;
select `count` into cnt from `news_data_total_news` limit 1;
set newcnt = cnt + 1;
update `news_data_total_news` set `count` = newcnt where `count` = cnt;
end//

它奏效了。

还有一件事,我们可以有多个定义了不同分隔符的 ResourceDatabasePopulator 对象。

ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator(false, false, StandardCharsets.UTF_8.toString(), new ClassPathResource("data.sql"));
        resourceDatabasePopulator.execute(dataSource);
        
ResourceDatabasePopulator triggersPopulator = new ResourceDatabasePopulator(false, false, StandardCharsets.UTF_8.toString(), new ClassPathResource("triggers.sql"));
        triggersPopulator.setSeparator("//");
        triggersPopulator.execute(dataSource);

如您所见,我有两个 ResourceDatabasePopulator 对象来加载两个不同的 sql 脚本,data.sql 使用默认分隔符,triggers.sql 使用 // 作为分隔符。