从 jdbc 呼叫 sqlj.install_jar?
calling sqlj.install_jar from jdbc?
我有一个 python 片段,我尝试移植到 java。目标是 Gradle 但我无法让它工作,所以我想我会从普通的 JDBC 开始。 python 代码如下所示:
import argparse
import ibm_db
import sys
def main(hostname, database, username, password):
connstr = f"DATABASE={database};HOSTNAME={hostname};PORT=50000;PROTOCOL=TCPIP;UID={username}; PWD={password}"
conn = ibm_db.connect(connstr, "", "")
s1 = ibm_db.prepare(conn, "call sqlj.install_jar('file:/tmp/commons.jar', 'StringUtil_TEST')")
ibm_db.execute(s1, ())
# print(ibm_db.fetch_tuple(s1)[0])
ibm_db.commit(conn)
sys.exit(0)
并且有效。 jar 文件按预期最终位于目标主机上的 ~/sqllib/function/jar/DB2INST1 中。
我看过 java 中的几个示例并尝试模仿它们,但我总是以错误告终(其中大部分可能是因为我在 java).我目前的代码是:
public static void main(String argv[])
{
try {
Connection con = null;
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
con = DriverManager.getConnection(<host>, <user>, <passwd>);
CallableStatement callStmt1 = null;
callStmt1 = con.prepareCall("call sqlj.install_jar('" + "file:/tmp/commons.jar" + "', 'StringUtil_TEST2')");
// tried this as well
// callStmt1 = con.prepareCall("call sqlj.install_jar('" + "file:/tmp/commons.jar" + "', 'StringUtil_TEST2', 0)");
callStmt1.execute();
}
catch (Exception e)
{
//System.out.println(e.);
e.printStackTrace();
}
}
}
编译为:
#> javac -cp db2jcc4.jar aa.java
和运行为:
#> java -cp .:db2jcc4.jar Aa
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=SQLJ.INSTALL_JAR;PROCEDURE, DRIVER=4.29.24
at com.ibm.db2.jcc.am.b7.a(b7.java:810)
at com.ibm.db2.jcc.am.b7.a(b7.java:66)
at com.ibm.db2.jcc.am.b7.a(b7.java:140)
at com.ibm.db2.jcc.am.k9.c(k9.java:2844)
at com.ibm.db2.jcc.am.k9.d(k9.java:2828)
at com.ibm.db2.jcc.am.k9.a(k9.java:2254)
at com.ibm.db2.jcc.am.k_.a(k_.java:8277)
at com.ibm.db2.jcc.t4.ab.i(ab.java:204)
at com.ibm.db2.jcc.t4.ab.e(ab.java:133)
at com.ibm.db2.jcc.t4.p.d(p.java:63)
at com.ibm.db2.jcc.t4.av.m(av.java:190)
at com.ibm.db2.jcc.am.k9.am(k9.java:2249)
at com.ibm.db2.jcc.am.k_.bs(k_.java:3778)
at com.ibm.db2.jcc.am.k_.a(k_.java:4640)
at com.ibm.db2.jcc.am.CallableStatement.b(CallableStatement.java:136)
at com.ibm.db2.jcc.am.CallableStatement.a(CallableStatement.java:105)
at com.ibm.db2.jcc.am.CallableStatement.execute(CallableStatement.java:95)
at Aa.main(aa.java:28)
的含义
SQL0440N No authorized routine named "<routine-name>" of type
"<routine-type>" having compatible arguments was found.
我原以为错误会发生在准备期间,但它发生在执行期间
所以我不知道该怎么做。
是否有人可以分享从 jdbc 调用 sqlj.install_jar 的工作片段?
当我调用 sqlj.install_jar
时,在 jdbc 的 Db2-LUW v11.5.6.0 上,我遇到了与您的问题相同的 -440 症状。
可能是我的一些倒退或错误。
比较方法 DB2Connection.installDB2JavaStoredProcedure
的行为也可能是值得的(据说 运行s sqlj.install_jar
)
但是替代方法 sqlj.DB2_INSTALL_JAR
目前对我来说从 jdbc 开始就可以了。
下面的示例基于 IBM 的示例代码,我 运行 它在本地 Db2-LUW 服务器上,因此使用无密码样式 url。
请注意,如果您需要使其重新启用运行,则必须对其进行扩展,以检查 sysibm.sysjarobjects
是否为 jar_id ,请使用 sqlj.replace_jar
and/or sqlj.remove_jar
和 sqlj.refresh_classes()
视情况而定。出于这个原因,我更喜欢使用 shell-script 而不是 jdbc 来编排我的构建脚本,代价是在构建主机名上有一个正确配置的 Db2-client。在我的案例中,shell 脚本比 jdbc 代码更短且更易于管理。
import java.sql.*;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class installj {
public static void main(String[] args) {
String url = "jdbc:db2:sample"; // url syntax for passwordless connection local on Db2-server
String user = "";
String password = "";
Connection con;
CallableStatement callStmt;
String returnedVarchar="";
String jarid = "MYJARID";
String jarfile = "/home/user1/test/jarname.jar";
try {
Class.forName("com.ibm.db2.jcc.DB2Driver") ;
// the URL format is specifically for a Type-2 passwordless local connection
con = DriverManager.getConnection(url, user, password);
con.setAutoCommit(false);
File aFile = new File(jarfile);
FileInputStream inputStream = new FileInputStream(aFile);
CallableStatement stmt;
String sql = "Call SQLJ.DB2_INSTALL_JAR(?, ?, ?)";
stmt = con.prepareCall(sql);
stmt.setBinaryStream(1, inputStream, (int)aFile.length());
stmt.setString(2, jarid);
stmt.setInt(3, 0);
boolean isrs = stmt.execute();
stmt.close();
System.out.println("\n\nInstallation of JAR succeeded\n\n");
con.commit();
con.close();
}
catch (FileNotFoundException e) {
System.err.println("\nCaught exception FileNot Found\n");
e.printStackTrace();
}
catch (ClassNotFoundException e) {
System.err.println("Could not load JDBC driver");
System.out.println("Exception: " + e);
e.printStackTrace();
}
catch (SQLException ex) {
System.err.println("---> SQLException information\n");
while (ex != null) {
System.err.println("\nError msg: " + ex.getMessage());
System.err.println("\nSQLSTATE: " + ex.getSQLState());
System.err.println("\nError code: " + ex.getErrorCode());
ex.printStackTrace();
ex = ex.getNextException();
}
}
}
}
试试这个:
Connection con = null;
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
con = DriverManager.getConnection(<host>, <user>, <passwd>);
DB2Connection db2con = (DB2Connection) con;
FileInputStream is = new FileInputStream("/tmp/commons.jar");
db2con.installDB2JavaStoredProcedure(is, (int) is.getChannel().size(), "StringUtil_TEST2");
...
// if replaceDB2JavaStoredProcedure is used it is necessary
// to refresh classes to load the new jar
CallableStatement callStmt1 = null;
callStmt1 = db2con.prepareCall("call sqlj.refresh_classes()");
callStmt1.execute();
我有一个 python 片段,我尝试移植到 java。目标是 Gradle 但我无法让它工作,所以我想我会从普通的 JDBC 开始。 python 代码如下所示:
import argparse
import ibm_db
import sys
def main(hostname, database, username, password):
connstr = f"DATABASE={database};HOSTNAME={hostname};PORT=50000;PROTOCOL=TCPIP;UID={username}; PWD={password}"
conn = ibm_db.connect(connstr, "", "")
s1 = ibm_db.prepare(conn, "call sqlj.install_jar('file:/tmp/commons.jar', 'StringUtil_TEST')")
ibm_db.execute(s1, ())
# print(ibm_db.fetch_tuple(s1)[0])
ibm_db.commit(conn)
sys.exit(0)
并且有效。 jar 文件按预期最终位于目标主机上的 ~/sqllib/function/jar/DB2INST1 中。
我看过 java 中的几个示例并尝试模仿它们,但我总是以错误告终(其中大部分可能是因为我在 java).我目前的代码是:
public static void main(String argv[])
{
try {
Connection con = null;
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
con = DriverManager.getConnection(<host>, <user>, <passwd>);
CallableStatement callStmt1 = null;
callStmt1 = con.prepareCall("call sqlj.install_jar('" + "file:/tmp/commons.jar" + "', 'StringUtil_TEST2')");
// tried this as well
// callStmt1 = con.prepareCall("call sqlj.install_jar('" + "file:/tmp/commons.jar" + "', 'StringUtil_TEST2', 0)");
callStmt1.execute();
}
catch (Exception e)
{
//System.out.println(e.);
e.printStackTrace();
}
}
}
编译为:
#> javac -cp db2jcc4.jar aa.java
和运行为:
#> java -cp .:db2jcc4.jar Aa
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=SQLJ.INSTALL_JAR;PROCEDURE, DRIVER=4.29.24
at com.ibm.db2.jcc.am.b7.a(b7.java:810)
at com.ibm.db2.jcc.am.b7.a(b7.java:66)
at com.ibm.db2.jcc.am.b7.a(b7.java:140)
at com.ibm.db2.jcc.am.k9.c(k9.java:2844)
at com.ibm.db2.jcc.am.k9.d(k9.java:2828)
at com.ibm.db2.jcc.am.k9.a(k9.java:2254)
at com.ibm.db2.jcc.am.k_.a(k_.java:8277)
at com.ibm.db2.jcc.t4.ab.i(ab.java:204)
at com.ibm.db2.jcc.t4.ab.e(ab.java:133)
at com.ibm.db2.jcc.t4.p.d(p.java:63)
at com.ibm.db2.jcc.t4.av.m(av.java:190)
at com.ibm.db2.jcc.am.k9.am(k9.java:2249)
at com.ibm.db2.jcc.am.k_.bs(k_.java:3778)
at com.ibm.db2.jcc.am.k_.a(k_.java:4640)
at com.ibm.db2.jcc.am.CallableStatement.b(CallableStatement.java:136)
at com.ibm.db2.jcc.am.CallableStatement.a(CallableStatement.java:105)
at com.ibm.db2.jcc.am.CallableStatement.execute(CallableStatement.java:95)
at Aa.main(aa.java:28)
的含义
SQL0440N No authorized routine named "<routine-name>" of type
"<routine-type>" having compatible arguments was found.
我原以为错误会发生在准备期间,但它发生在执行期间 所以我不知道该怎么做。
是否有人可以分享从 jdbc 调用 sqlj.install_jar 的工作片段?
当我调用 sqlj.install_jar
时,在 jdbc 的 Db2-LUW v11.5.6.0 上,我遇到了与您的问题相同的 -440 症状。
可能是我的一些倒退或错误。
比较方法 DB2Connection.installDB2JavaStoredProcedure
的行为也可能是值得的(据说 运行s sqlj.install_jar
)
但是替代方法 sqlj.DB2_INSTALL_JAR
目前对我来说从 jdbc 开始就可以了。
下面的示例基于 IBM 的示例代码,我 运行 它在本地 Db2-LUW 服务器上,因此使用无密码样式 url。
请注意,如果您需要使其重新启用运行,则必须对其进行扩展,以检查 sysibm.sysjarobjects
是否为 jar_id ,请使用 sqlj.replace_jar
and/or sqlj.remove_jar
和 sqlj.refresh_classes()
视情况而定。出于这个原因,我更喜欢使用 shell-script 而不是 jdbc 来编排我的构建脚本,代价是在构建主机名上有一个正确配置的 Db2-client。在我的案例中,shell 脚本比 jdbc 代码更短且更易于管理。
import java.sql.*;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class installj {
public static void main(String[] args) {
String url = "jdbc:db2:sample"; // url syntax for passwordless connection local on Db2-server
String user = "";
String password = "";
Connection con;
CallableStatement callStmt;
String returnedVarchar="";
String jarid = "MYJARID";
String jarfile = "/home/user1/test/jarname.jar";
try {
Class.forName("com.ibm.db2.jcc.DB2Driver") ;
// the URL format is specifically for a Type-2 passwordless local connection
con = DriverManager.getConnection(url, user, password);
con.setAutoCommit(false);
File aFile = new File(jarfile);
FileInputStream inputStream = new FileInputStream(aFile);
CallableStatement stmt;
String sql = "Call SQLJ.DB2_INSTALL_JAR(?, ?, ?)";
stmt = con.prepareCall(sql);
stmt.setBinaryStream(1, inputStream, (int)aFile.length());
stmt.setString(2, jarid);
stmt.setInt(3, 0);
boolean isrs = stmt.execute();
stmt.close();
System.out.println("\n\nInstallation of JAR succeeded\n\n");
con.commit();
con.close();
}
catch (FileNotFoundException e) {
System.err.println("\nCaught exception FileNot Found\n");
e.printStackTrace();
}
catch (ClassNotFoundException e) {
System.err.println("Could not load JDBC driver");
System.out.println("Exception: " + e);
e.printStackTrace();
}
catch (SQLException ex) {
System.err.println("---> SQLException information\n");
while (ex != null) {
System.err.println("\nError msg: " + ex.getMessage());
System.err.println("\nSQLSTATE: " + ex.getSQLState());
System.err.println("\nError code: " + ex.getErrorCode());
ex.printStackTrace();
ex = ex.getNextException();
}
}
}
}
试试这个:
Connection con = null;
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
con = DriverManager.getConnection(<host>, <user>, <passwd>);
DB2Connection db2con = (DB2Connection) con;
FileInputStream is = new FileInputStream("/tmp/commons.jar");
db2con.installDB2JavaStoredProcedure(is, (int) is.getChannel().size(), "StringUtil_TEST2");
...
// if replaceDB2JavaStoredProcedure is used it is necessary
// to refresh classes to load the new jar
CallableStatement callStmt1 = null;
callStmt1 = db2con.prepareCall("call sqlj.refresh_classes()");
callStmt1.execute();