簡體   English   中英

如何從groovy調用parametrize sql過程

[英]How to call parametrize sql procedure from groovy

我從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

為了比上面的@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異常。

基本上String + GString = String。 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實例,然后它將沿着'plus'調用級聯,因此您可以確保Groovy SQL獲得創建'正確'綁定列表/ SQL所需的輸入。

我對此並不熟悉,但只是通過文檔挖掘這是我所看到的,以及可能發生的其他可能性 -

  1. 該參數需要是一個與StringGString 希望它確實被轉換,但是通過用變量組合一個字符串然后將它轉換為GString對象作為[ GString info ]顯式嘗試

     GString g = GString.EMPTY + normal_str_variable; 
  2. schema變量未設置適當的值。

  3. Sql實例可能已關閉,您可能無法正確檢查。

希望它是一個重復的問題從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;
    }
 }

希望這可以幫到你。 謝謝。

這個問題要求groovy解決方案,所以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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM