4

我正在从 groovy 运行一些程序:

    sql.call("{call SCHEMA.NAME_PROCEDURE($par1,$par2,$par3)}"){}

其中 sql 是数据库连接的实例

这很好用。

现在我需要参数化 SCHEMA 所以我尝试这样的事情:

    sql.call("{call ${schema}.NAME_PROCEDURE($par1,$par2,$par3)}"){}

或者

    sql.call("{call " + schema + ".NAME_PROCEDURE($par1,$par2,$par3)}"){}

但没有成功。我不知道为什么这两个代码片段不起作用。还有一些sqlException。我做错了什么?

请帮忙

编辑:

我发现了类似的问题,但仍然没有答案:

http://groovy.329449.n5.nabble.com/Calling-stored-procedures-td344943.html

4

4 回答 4

2

为了比上面@mtk 的答案更明确,请尝试更改:

sql.call("{call " + schema + ".NAME_PROCEDURE($par1,$par2,$par3)}"){}

到:

sql.call(GString.EMPTY + "{call " + schema + ".NAME_PROCEDURE($par1,$par2,$par3)}"){}

您的第一次尝试将不起作用-这是尝试绑定过程的名称,它将生成以下形式的 SQL:

 { call ?.NAME_PROCEDURE(?,?,?) }

第二个稍微不那么明显。Groovy SQL 使用 GString 对象来生成 SQL 和绑定列表。但是,因为您从原始字符串开始,表达式的结果将是原始字符串,所以传递给 sql.call 的内容如下所示:

 { call schema.NAME_PROCEDURE(par1,par2,par2) }

不是:

 { call schema.NAME_PROCEDURE(${par1},${par2},${par3}) }

这是你真正想要的。如果 par1-3 都是数字,你可以接受,但如果它们是字符串(或其他一些会通过替换被强制转换为字符串的类型),这可能不是有效的 SQL,因此你的 SQL 异常。

基本上字符串 + GString = 字符串。Groovy SQL 需要一个 GString 实例,以便它可以为此查询正确设置绑定列表。

您可以通过将字符串强制为“GString”实例来解决此问题。GString 被定义为 GString + String = GString。您可以在 groovy 控制台上看到这一点:

groovy> def par1 = 1 
groovy> def par2 = 2 
groovy> def par3 = 3 
groovy> def schema = 'myschema' 
groovy> println (("{call " + schema + ".NAME_PROCEDURE($par1,$par2,$par3)}").class) 
groovy> println ((GString.EMPTY + "{call " + schema + ".NAME_PROCEDURE($par1,$par2,$par3)}").class) 

class java.lang.String
class groovy.lang.GString$2

通过将“{call”强制为 GString 实例,这将沿着“加号”调用级联,因此您可以确保 Groovy SQL 获得创建“正确”绑定列表/SQL 所需的输入。

于 2013-02-20T18:59:59.710 回答
1

我对此并不精通,但只是在文档中挖掘这就是我所看到的,以及可能发生的其他可能性 -

  1. 参数期望是 aGString与 不同String。希望它确实被转换了,但是通过用变量组合一个字符串来显式地尝试,然后将它转换为一个 GString 对象作为 [ GString info ]

    GString g = GString.EMPTY + normal_str_variable; 
    
  2. schema变量未设置正确的值。

  3. Sql 实例可能已关闭并且您没有正确检查。

于 2013-02-20T10:20:32.403 回答
0

希望它是从 Java / JPA 调用存储过程的问题的重复

但我的回答是:查看代码片段

//getDBUSERByUserId is a stored procedure
String getDBUSERByUserIdSql = "{call getDBUSERByUserId(?,?,?,?)}";
callableStatement = dbConnection.prepareCall(getDBUSERByUserIdSql);
callableStatement.setInt(1, 10);
callableStatement.registerOutParameter(2, java.sql.Types.VARCHAR);
callableStatement.registerOutParameter(3, java.sql.Types.VARCHAR);
callableStatement.registerOutParameter(4, java.sql.Types.DATE);

// execute getDBUSERByUserId store procedure
callableStatement.executeUpdate();

String userName = callableStatement.getString(2);
String createdBy = callableStatement.getString(3);
Date createdDate = callableStatement.getDate(4);

示例代码:

存储过程:

CREATE OR REPLACE PROCEDURE getDBUSERByUserId(
       p_userid IN DBUSER.USER_ID%TYPE,
       o_username OUT DBUSER.USERNAME%TYPE,
       o_createdby OUT  DBUSER.CREATED_BY%TYPE,
       o_date OUT DBUSER.CREATED_DATE%TYPE)
IS
BEGIN

  SELECT USERNAME , CREATED_BY, CREATED_DATE
  INTO o_username, o_createdby,  o_date 
  FROM  DBUSER WHERE USER_ID = p_userid;

END;

通过 CallableStatement 调用存储过程

public class JDBCCallableStatementOUTParameterExample {

    private static final String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";
    private static final String DB_CONNECTION = "jdbc:oracle:thin:@localhost:1521:MKYONG";
    private static final String DB_USER = "user";
    private static final String DB_PASSWORD = "password";

    public static void main(String[] argv) {
        try {
            callOracleStoredProcOUTParameter();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
    private static void callOracleStoredProcOUTParameter() throws SQLException {
        Connection dbConnection = null;
        CallableStatement callableStatement = null;
        String getDBUSERByUserIdSql = "{call getDBUSERByUserId(?,?,?,?)}";
        try {
            dbConnection = getDBConnection();
            callableStatement = dbConnection.prepareCall(getDBUSERByUserIdSql);
            callableStatement.setInt(1, 10);
            callableStatement.registerOutParameter(2, java.sql.Types.VARCHAR);
            callableStatement.registerOutParameter(3, java.sql.Types.VARCHAR);
            callableStatement.registerOutParameter(4, java.sql.Types.DATE);
            // execute getDBUSERByUserId store procedure
            callableStatement.executeUpdate();
            String userName = callableStatement.getString(2);
            String createdBy = callableStatement.getString(3);
            Date createdDate = callableStatement.getDate(4);
            System.out.println("UserName : " + userName);
            System.out.println("CreatedBy : " + createdBy);
            System.out.println("CreatedDate : " + createdDate);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        } finally {
            if (callableStatement != null) {
                callableStatement.close();
            }
            if (dbConnection != null) {
                dbConnection.close();
            }
        }
    }
    private static Connection getDBConnection() {
        Connection dbConnection = null;
        try {
            Class.forName(DB_DRIVER);
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
        try {
            dbConnection = DriverManager.getConnection(
                DB_CONNECTION, DB_USER,DB_PASSWORD);
            return dbConnection;
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return dbConnection;
    }
 }

希望这可以帮助你。谢谢。

于 2013-02-21T04:49:15.433 回答
0

这个问题要求常规的解决方案,所以 vanilla java 是不合时宜的。这是一个使用“内联过程”来更好地处理参数的解决方案。在 grails 2.4 之后还有一个 sql.callWithRows 和 sql.callWithAllRows 可用

    def calculateTotals(map) {
    //initialize variables
    Double returnTotalOriginalOut = 0
    Double returnTotalOtherOut = 0
    Double returnTotalNetOut = 0

    def sql = new Sql(sessionFactory.currentSession.connection())
    //calculate the totals
    sql.call("""
             DECLARE
                return_orig_chgs      number := 0;
                return_non_orig_chgs  number := 0;
                return_net_inst_chgs  number := 0;
             BEGIN
               SCHEMA.NAME_PROCEDURE(id         => ${map.id},
                                     term_in        => ${map.term},
                                     orig_chgs      => return_orig_chgs,
                                     non_orig_chgs  => return_non_orig_chgs,
                                     net_inst_chgs  => return_net_inst_chgs);
             ${Sql.DOUBLE} := return_orig_chgs;
             ${Sql.DOUBLE} := return_non_orig_chgs;
             ${Sql.DOUBLE} := return_net_inst_chgs;
            END ;
    """) { return_orig_chgs, return_non_orig_chgs, return_net_inst_chgs ->
        returnTotalOriginalOut = return_orig_chgs
        returnTotalOtherOut = return_non_orig_chgs
        returnTotalNetOut = return_net_inst_chgs
    }

    def returnMap = [:]
    returnMap = [returnTotalOriginal: returnTotalOriginalOut, returnTotalOther: returnTotalOtherOut, returnTotalNet: returnTotalNetOut]
    return returnMap
}
于 2015-01-13T23:34:39.570 回答