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)}"){}

しかし、成功しませんでした。この 2 つのコードの断片が機能しない理由がわかりません。まだいくつかの 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(?,?,?) }

2 番目のものは少しわかりにくいです。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 を作成するために必要な入力を確実に取得できるようになります。

于 2013-02-20T18:59:59.710 に答える
1

私はこれに精通していませんが、ドキュメントを掘り下げるだけで、これが私が見ているものであり、発生する可能性のある他の可能性があります-

  1. パラメータは とは異なる である必要がGStringありStringます。変換されることを願っていますが、変数を使用して文字列を作成し、後で [ GString info ]として GString オブジェクトに変換することで明示的に試みます。

    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

質問はグルーヴィーなソリューションを求めているため、バニラ 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 に答える