【问题标题】:Hibernate - Cannot Create Stored Procedure休眠 - 无法创建存储过程
【发布时间】:2020-11-02 00:24:27
【问题描述】:

我最近从使用预填充的数据库切换到允许 Hibernate 创建我的表。尝试在我的 data.sql 中创建存储过程时,出现以下错误:

Exception in thread "task-2" org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #7 of URL [file:/C:/Users/samuel/IdeaProjects/Capripol/target/classes/data.sql]: CREATE PROCEDURE CalculateUserRating( IN baseRating NUMERIC(5,2), IN userID int, IN focusID int, OUT userRating NUMERIC(5,2)) BEGIN SELECT IFNULL(baseRating + SUM(s.sightingValue), baseRating) INTO userRating FROM Sighting s WHERE s.sighteeUserID = userID AND s.sightedFocusID = focusID AND s.sighterUserID != userID; nested exception is java.sql.SQLSyntaxErrorException: 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 '' at line 1

我尝试将?allowMultiQueries=true 添加到我的spring.datasource.url 中,但没有任何区别。同样,我尝试了this answer,也没有任何区别。

data.sql:

DROP PROCEDURE IF EXISTS CalculateUserRating;
CREATE PROCEDURE CalculateUserRating(
    IN baseRating NUMERIC(5,2),
    IN userID int,
    IN focusID int,
    OUT userRating NUMERIC(5,2))
BEGIN
    SELECT IFNULL(baseRating + SUM(s.sightingValue), baseRating)
           INTO userRating
    FROM Sighting s
    WHERE
            s.sighteeUserID = userID
      AND
            s.sightedFocusID = focusID
      AND
            s.sighterUserID != userID;

END;

DROP PROCEDURE IF EXISTS CalculateSightingValue;
CREATE PROCEDURE CalculateSightingValue(
    IN baseRating int,
    IN userID int,
    IN focusID int,
    OUT sightingValue NUMERIC(5,2))
BEGIN
    CALL CalculateUserRating(baseRating, userID, focusID, @userRating);
    SELECT (@userRating/100)
           INTO sightingValue;
END;

#If first sighting it will return 1 as user rating.

DROP PROCEDURE IF EXISTS GetSightingSummary;
CREATE PROCEDURE GetSightingSummary(
    IN userID int,
    IN focusID int,
    OUT totalSightings int,
    OUT selfSightings int,
    OUT peerSightings int,
    OUT otherSightings int)
BEGIN
    SELECT count(*) INTO totalSightings
    FROM Sighting s
    WHERE
            s.sighteeUserID = userID;
    SELECT count(*) INTO selfSightings
    FROM Sighting s
    WHERE
            s.sighteeUserID = s.sighterUserID
      AND
            s.sighteeUserID = userID;
    SELECT count(*) INTO peerSightings
    FROM Sighting s
    WHERE
            s.sighteeUserID = userID
      AND
            s.sightedFocusID = focusID
      AND
            s.sighterUserID != userID;

END;

编辑:

我尝试在脚本的开头和结尾添加DELIMITER //,并尝试在每个单独的过程之间放置一个分隔符,但没有任何区别。但是,根据this,分隔符不是必需的。

DELIMITER //
DROP PROCEDURE IF EXISTS CalculateUserRating;
DROP PROCEDURE IF EXISTS CalculateSightingValue;
DROP PROCEDURE IF EXISTS GetSightingSummary;
CREATE PROCEDURE CalculateUserRating(
    IN baseRating NUMERIC(5,2),
    IN userID int,
    IN focusID int,
    OUT userRating NUMERIC(5,2))
BEGIN
    SELECT IFNULL(baseRating + SUM(s.sightingValue), baseRating)
           INTO userRating
    FROM Sighting s
    WHERE
            s.sighteeUserID = userID
      AND
            s.sightedFocusID = focusID
      AND
            s.sighterUserID != userID;

END;

CREATE PROCEDURE CalculateSightingValue(
    IN baseRating int,
    IN userID int,
    IN focusID int,
    OUT sightingValue NUMERIC(5,2))
BEGIN
    CALL CalculateUserRating(baseRating, userID, focusID, @userRating);
    SELECT (@userRating/100)
           INTO sightingValue;
END;

#If first sighting it will return 1 as user rating.


CREATE PROCEDURE GetSightingSummary(
    IN userID int,
    IN focusID int,
    OUT totalSightings int,
    OUT selfSightings int,
    OUT peerSightings int,
    OUT otherSightings int)
BEGIN
    SELECT count(*) INTO totalSightings
    FROM Sighting s
    WHERE
            s.sighteeUserID = userID;
    SELECT count(*) INTO selfSightings
    FROM Sighting s
    WHERE
            s.sighteeUserID = s.sighterUserID
      AND
            s.sighteeUserID = userID;
    SELECT count(*) INTO peerSightings
    FROM Sighting s
    WHERE
            s.sighteeUserID = userID
      AND
            s.sightedFocusID = focusID
      AND
            s.sighterUserID != userID;

END//
DELIMITER ;

完整的错误堆栈跟踪:

Exception in thread "task-2" org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #10 of URL [file:/C:/Users/samuel/IdeaProjects/Capripol/target/classes/data.sql]: CREATE PROCEDURE CalculateUserRating( IN baseRating NUMERIC(5,2), IN userID int, IN focusID int, OUT userRating NUMERIC(5,2)) BEGIN SELECT IFNULL(baseRating + SUM(s.sightingValue), baseRating) INTO userRating FROM Sighting s WHERE s.sighteeUserID = userID AND s.sightedFocusID = focusID AND s.sighterUserID != userID; nested exception is java.sql.SQLSyntaxErrorException: 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 '' at line 1
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:622)
    at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:254)
    at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:49)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runScripts(DataSourceInitializer.java:202)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.initSchema(DataSourceInitializer.java:119)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker.onApplicationEvent(DataSourceInitializerInvoker.java:91)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker.onApplicationEvent(DataSourceInitializerInvoker.java:38)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361)
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.publishEventIfRequired(DataSourceInitializedPublisher.java:99)
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.access$100(DataSourceInitializedPublisher.java:50)
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher$DataSourceSchemaCreatedPublisher.lambda$postProcessEntityManagerFactory$0(DataSourceInitializedPublisher.java:200)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLSyntaxErrorException: 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 '' at line 1
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
    at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:764)
    at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:648)
    at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95)
    at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:601)
    ... 17 more

【问题讨论】:

    标签: java mysql hibernate


    【解决方案1】:

    MySQL 需要 DELIMITER 在 coammnd 之前和之后,因为它必须确定存储过程或函数的开始和结束位置。

    我也重新安排了一下,因为命令不想运行,否则

    USE testdb;
    DELIMITER //
    DROP PROCEDURE IF EXISTS CalculateUserRating;
    DROP PROCEDURE IF EXISTS CalculateSightingValue;
    DROP PROCEDURE IF EXISTS GetSightingSummary;
    CREATE PROCEDURE CalculateUserRating(
        IN baseRating NUMERIC(5,2),
        IN userID int,
        IN focusID int,
        OUT userRating NUMERIC(5,2))
    BEGIN
        SELECT IFNULL(baseRating + SUM(s.sightingValue), baseRating)
               INTO userRating
        FROM Sighting s
        WHERE
                s.sighteeUserID = userID
          AND
                s.sightedFocusID = focusID
          AND
                s.sighterUserID != userID;
    
    END;
    
    CREATE PROCEDURE CalculateSightingValue(
        IN baseRating int,
        IN userID int,
        IN focusID int,
        OUT sightingValue NUMERIC(5,2))
    BEGIN
        CALL CalculateUserRating(baseRating, userID, focusID, @userRating);
        SELECT (@userRating/100)
               INTO sightingValue;
    END;
    
    #If first sighting it will return 1 as user rating.
    
    
    CREATE PROCEDURE GetSightingSummary(
        IN userID int,
        IN focusID int,
        OUT totalSightings int,
        OUT selfSightings int,
        OUT peerSightings int,
        OUT otherSightings int)
    BEGIN
        SELECT count(*) INTO totalSightings
        FROM Sighting s
        WHERE
                s.sighteeUserID = userID;
        SELECT count(*) INTO selfSightings
        FROM Sighting s
        WHERE
                s.sighteeUserID = s.sighterUserID
          AND
                s.sighteeUserID = userID;
        SELECT count(*) INTO peerSightings
        FROM Sighting s
        WHERE
                s.sighteeUserID = userID
          AND
                s.sightedFocusID = focusID
          AND
                s.sighterUserID != userID;
    
    END//
    DELIMITER ;
    

    【讨论】:

    • 不幸的是,这似乎没有什么不同,我仍然得到同样的错误
    • 真的一样吗?你能把它添加到你的问题中吗
    • 我已经相应添加了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多