JDBC 代码调用返回值的存储函数时出错

Posted

技术标签:

【中文标题】JDBC 代码调用返回值的存储函数时出错【英文标题】:Error in JDBC code calling a stored function which returns a value 【发布时间】:2016-12-05 16:04:29 【问题描述】:

我正在尝试从 JDBC 代码中打印存储的 mysql 函数 的返回值,如下所示(我使用的是 MySQL Server 5.7.13):

package jdbc;

import java.sql.DriverManager;
import java.sql.*;
import java.util.Scanner;


public class CallableStatementsCallingFunctions 
    public static void main(String... syrt)
    
      try
     
        try
                        
            Class.forName("com.mysql.jdbc.Driver");
        
        catch(ClassNotFoundException e)
        
          System.out.println("Error(class): "+ e);
        
        try
        
         Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/collablestatement","root","mysql") ;
         CallableStatement cs = conn.prepareCall("call ?:=getBalance1(?)");
         String s = new Scanner(System.in).nextLine();
         cs.registerOutParameter(1,Types.INTEGER);
         cs.setInt(2,Integer.parseInt(s));             
         cs.execute();
         System.out.println("Account number :" + cs.getInt(1));
         conn.close();
         
        catch(SQLException e)
        
          System.out.println("Error(SQL) : "+e);
        
    
    catch(Exception e)
    
      System.out.println("Error(Fro outer try) : "+ e);
    

这里显示了存储的函数getBalance1(acno)

我的代码输出在这里显示

我得到了 SQL 命令的输出,但是在 JDBC 中我得到了,SQLException

参数1不是输出参数

我知道参数 1 已被用作 jdbc 代码中函数返回值的占位符。在 prepareCall 中,我也尝试了语法 - ?:= call getBalance1(?) ,但即使这样也得到了相同的异常。

为什么会出现异常?

【问题讨论】:

快速猜测是 cs.getString("1"); 【参考方案1】:

我认为我收到了 SQLException,因为我使用的是 jdk1.8.xx,其中调用存储函数的语法不同。通过替换语句解决了问题

CallableStatement cs = conn.prepareCall("call ?:=getBalance1(?)");

在代码中

CallableStatement cs = conn.prepareCall("? = call getBalance1(?)");

prepareCall()方法中作为参数调用函数的语法为here。

【讨论】:

我认为 Java 8 中的语法没有发生任何变化。您在原始语句中只是有一个错字(额外的冒号 + 错误的 call 关键字)。【参考方案2】:

getBalance1() 是 MySQL FUNCTION,而不是 PROCEDURE,所以我不希望使用 JDBC CallableStatement

即使在您使用的 MySQL 控制台测试中

select getBalance1(103)

所以你只需要使用PreparedStatement在你的Java代码中做同样的事情:

PreparedStatement ps = conn.prepareStatement("select getBalance1(?)");
ps.setInt(1) = 103;
ResultSet rs = ps.executeQuery();
rs.next();
Double bal = rs.getDouble(1);

(需要注意的是,由于“余额”显然是指“钱”,所以REAL不是列类型的好选择;详情here。)

【讨论】:

我得到了你在这里写的东西。但是如果我使用 PreparedStatement 来代替 CallableStatement 接口将用于什么?我正在尝试使用 CallableStatement 获得结果,因为那时我可能会遇到很多问题。 CallableStatement 是 JDBC 运行存储过程的方式,在 MySQL 中使用 CREATE PROCEDURE 创建并在 MySQL 中使用 CALL procedurename 调用。您已使用 CREATE FUNCTION 创建了一个用户定义的函数,通常通过将其包含在表达式中来调用该函数,例如,作为 SELECT 语句的一部分。 其实也可以用CallableStatements调用SQLFUNCTIONs。对此的 JDBC 语法是 myConnection.prepareCall("? = call my_function(?)");,正如 OP 编写的答案所示。

以上是关于JDBC 代码调用返回值的存储函数时出错的主要内容,如果未能解决你的问题,请参考以下文章

调用返回值的数据库存储函数或存储过程

关于jdbc调用存储过程的问题

调用释放已存储值的 char 指针时,free() 函数失败

JS获取页面返回值的

procrdure存储过程

JDBC 调用函数或存储过程