我正在从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
答案 0 :(得分: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异常。
基本上是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 :(得分:1)
我对此并不熟悉,但只是挖掘documentation这就是我所看到的,以及可能发生的其他可能性 -
参数预期为GString
,与String
不同。希望它确实被转换,但是通过使用变量组合字符串并稍后将其转换为GString对象作为[GString info]
GString g = GString.EMPTY + normal_str_variable;
schema
变量未设置适当的值。
Sql实例可能已关闭,您可能无法正确检查。
答案 2 :(得分:0)
希望它与问题重复 Calling stored procedure from 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;
}
}
希望这可以帮到你。 感谢。
答案 3 :(得分: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
}