【问题标题】:How to call a MySQL stored procedure from Hibernate如何从 Hibernate 调用 MySQL 存储过程
【发布时间】:2012-12-30 08:51:52
【问题描述】:

我正在尝试从使用 MySQL 的 Java 应用程序调用 MySQL 存储过程。下面是 DAO 中我用来调用存储过程“insertComm”的部分

String opt="REFUND";
        Query query = this.getSession().createSQLQuery("CALL insertComm (:remitNo,     :opt)")
           .setParameter("remitNo", remitNo)
               .setParameter("opt", opt);
opt=query.toString();
hemappLogger.info(opt);

但是当我查询数据库并检查时,存储过程尚未执行。 'opt' 值显示为 SQLQueryImpl(CALL insertComm (:remitNo, :opt))

参数没问题,应用程序也没有显示错误。我看不到我错过了什么。

【问题讨论】:

    标签: java mysql database hibernate stored-procedures


    【解决方案1】:

    您没有将实体添加到会话对象中... .addEntity(classname.class).setParameter()

    【讨论】:

    【解决方案2】:

    很遗憾,您不能使用Session.createSQLQuery() 调用存储过程。顾名思义,它允许创建 SQL Query。过程调用不是查询。

    但不要害怕,解决方法是这样的。

    Connection conn = getSession().connection();
    CallableStatment stat = conn.prepareCall("{CALL insertComm (?,?)}");
    stat.setString(1, remitNo); // Assuming both parameters are String
    stat.setString(2, opt);
    
    stat.executeUpdate();
    stat.close();
    

    【讨论】:

    • 非常感谢。但我提到了link,这里是用户 createSqlquery。可能是我得到了一些不合适的东西。
    • 是的,该链接使用的是函数 (GetStocks) 而不是过程。函数将某些内容返回给调用者。但在你的情况下,正如你的名字所暗示的那样,它只是试图插入一些值。 GetStocks 函数将返回与作为参数发送的 stock_code 匹配的所有股票。并且由于在该示例中已经有一个用于股票(Stock 类)的表映射,所以它是可能的。
    • @shazin 如何从这里的 getSession() 获取会话???我正在使用休眠 4.2.2.Final。我正在使用 sessionFactory.getCurrentSession() 来获取休眠会话,但这里的会话没有方法 connect()。请回复...
    • @shazin CallableStatment 的库是什么?是 com.mysql.jdbc 还是 java.sql ???
    • @KJEjava48 java.sql
    【解决方案3】:

    假设您有一个输出基本类型的简单存储过程:

    CREATE PROCEDURE count_comments (
       IN postId INT, 
       OUT commentCount INT
    ) 
    BEGIN
        SELECT COUNT(*) INTO commentCount 
        FROM post_comment  
        WHERE post_comment.post_id = postId; 
    END
    

    您可以使用 JPA StoredProcedureQuery 调用此存储过程:

    StoredProcedureQuery query = entityManager
        .createStoredProcedureQuery("count_comments")
        .registerStoredProcedureParameter(
            "postId", Long.class, ParameterMode.IN)
        .registerStoredProcedureParameter(
            "commentCount", Long.class, ParameterMode.OUT)
        .setParameter("postId", 1L);
     
    query.execute();
     
    Long commentCount = (Long) query
        .getOutputParameterValue("commentCount");
    

    如果您的存储过程返回 REFCURSORTABLE 结果:

    CREATE PROCEDURE post_comments(IN postId INT) 
    BEGIN
        SELECT *  
        FROM post_comment   
        WHERE post_id = postId;  
    END
    

    你需要按如下方式调用存储过程:

    StoredProcedureQuery query = entityManager
        .createStoredProcedureQuery("post_comments");
    query.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN);
     
    query.setParameter(1, 1L);
     
    List<Object[]> postComments = query.getResultList();
    

    对于数据库函数,返回结果集而不是将其放入OUT 变量中:

    CREATE FUNCTION fn_count_comments(postId integer)
    RETURNS integer
    DETERMINISTIC 
    READS SQL DATA 
    BEGIN
        DECLARE commentCount integer; 
        SELECT COUNT(*) INTO commentCount 
        FROM post_comment  
        WHERE post_comment.post_id = postId; 
        RETURN commentCount; 
    END
    

    Hibernate 4.x 和 5.x API 对您没有帮助,您必须改用 JDBC:

    int commentCount = session.doReturningWork(connection -> {
        try (CallableStatement function = connection.prepareCall(
                "{ ? = call fn_count_comments(?) }")) {
            function.registerOutParameter(1, Types.INTEGER);
            function.setInt(2, 1);
            function.execute();
            return function.getInt(1);
        }
    });
    

    【讨论】:

    • 你知道如何使用休眠和存储过程从 mysql db 中获取特定列
    猜你喜欢
    • 2023-03-20
    • 2023-03-05
    • 1970-01-01
    • 2019-02-20
    • 2010-09-09
    • 2013-10-07
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多