【DM版本】:DM8
【操作系统】:Windows7或10 作为客户端 / Windows7 或 RHEL 6.5作为服务端
【CPU】:Intel 7700HQ
【问题描述】:大家好,以前在使用 Oracle 数据库时,采用以下类似的代码是可以在 Java 程序中调用输入参数为数组的存储过程,但是在使用达梦后,执行 stmt.execute(); 调用存储过程时报错
“dm.jdbc.driver.DMException: 网络通信异常”
相关存储过程如下:
AUTHID DEFINER
AS
/*变量说明部分*/
ppt varchar;
BEGIN
/*执行体*/
SELECT 123 INTO PARAM_SIZE FROM DUAL ;
for i in 1 .. PARAMS.count loop
PRINT PARAMS(i);
ppt:= PARAMS(i).key;
ppt:= PARAMS(i).value;
--v_param_map(v_params(i).key) := v_params(i).value;
end loop;
PRINT(PARAM_SIZE);
PARAM_SIZE:= 100;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
调用的相关方法如下:
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
Array param_set = null;
try {
param_set = procedureTool.getArray("PERSON.PARAM_SET", map);
List<Object> args = new ArrayList<>();
args.add(param_set);
List<Map<String, List>> results = procedureTool.callProcedure("PERSON.P_TEST2", args);
System.out.println(results);
} catch (Throwable e) {
e.printStackTrace();
}
……
public Array getArray(String typeName, Map<String, Object> objMap) throws SQLException {
Connection conn = dataSource.getConnection();
Object[][] paraArray = new Object[objMap.size()][2];
int i = 0;
for (Map.Entry entry : objMap.entrySet()) {
Object[] result = new Object[2];
result[0] = entry.getKey();
result[1] = entry.getValue();
paraArray[i] = result;
i++;
}
return conn.createArrayOf(typeName, paraArray);
}
……
public List<Map<String, List>> callProcedure(String procName, List<Object> args) {
//新建一个用于返回的列表
List<Map<String, List>> result = new ArrayList<>();
String caller = "call " + procName + "(";
for (Object arg : args) {
caller += "?,";
}
caller += "?)";
Connection conn = null;
//准备调用存储过程
CallableStatement stmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
stmt = conn.prepareCall(caller);
//赋值
for (int i = 1; i <= args.size(); i++) {
Object arg = args.get(i - 1);
if (arg instanceof Array) {
stmt.setArray(i, (Array) arg);
} else {
stmt.setObject(i, arg);
}
}
//注册返回游标
stmt.registerOutParameter(args.size() + 1, Types.OTHER);
//调用存储过程
stmt.execute();
如果将存储过程输入参数的数组改为普通的字符串,调用就没问题。
AUTHID DEFINER
AS
/*变量说明部分*/
--PARAM_ID INT;
BEGIN
/*执行体*/
SELECT PERSONID INTO PARAM_ID FROM PERSON.PERSON WHERE NAME = PARAM_NAME;
PRINT(PARAM_NAME);
PRINT(PARAM_ID);
EXCEPTION
WHEN OTHERS THEN NULL;
END;
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
Array param_set = null;
try {
param_set = procedureTool.getArray("PERSON.PARAM_SET", map);
List<Object> args = new ArrayList<>();
args.add("王刚");
List<Map<String, List>> results = procedureTool.callProcedure("PERSON.P_TEST", args);
System.out.println(results);
} catch (Throwable e) {
e.printStackTrace();
}
有朋友知道这是我哪里写的不正确,或是达梦暂时还不支持么?
问题解决了。或者说至少知道原因了。
最后在https://blog.csdn.net/ahriall/article/details/115250654
这篇文章中了解到了 DM8 的 JDBC 驱动不支持 Array,就试着退回了达梦7适配Java1.7 的驱动。没修改代码和数据库,能成功运行。
不过我环境是Java1.8 搭配达梦8… 不知道这样用下来会不会有问题 。叹气。
沉下去了… 尚未解决… 自己来顶顶…
希望知道的朋友路过留个言,谢谢… 一点思路也好