21. 无法执行该操作,因为链接服务器”Server_202”的 OLE DB 访问接口 “SQLNCLI10″ 无法启动分布式事务”
无法执行该操作,因为链接服务器”Server_202”的 OLE DB 访问接口 “SQLNCLI10″ 无法启动分布式事务”
原因:调用存储过程的方式有问题,必须用JDBC方式调用存储过程才可以正常调用。咋一看以为是分布式事务的问题。
数据库是sql server
解决方法:使用JDBC的方式调用存储过程代替普通调用方式。
代码如下:
运行报错的代码(普通方式:只有dao.impl中写代码):
/** * 查找符合条件的排污企业放入Map集合 * @param userName 登录名 * @return Map<String,Object> 键值对的集合 */ @Override public Map<String,Object> findAllCommunication(String userName) { //创建用于存储键值对的map集合 Map<String, Object> map = new HashMap<String, Object>(); //创建session对象 Session session = this.getSession(); //创建事务的对象 Transaction trans = session.beginTransaction(); //调用存储过程 SQLQuery query = session.createSQLQuery("{Call ProcYB_GetPSList(?)}"); //为存储过程设置输入参数 query.setString(0,userName == null ? "" : userName); //提交事务 trans.commit(); //获取存储过程的运行结果(得到的结果是Object类型的数组集合)存入list集合 List list = query.list(); //循环遍历该结果集合 for (int i = 0; i < list.size(); i++) { //用Object数组类型的对象objs接收每一次外层循换得到的对象 Object[] objs = (Object[]) list.get(i); //通过内层循环取出每一个objs集合中的数据放入map集合中 for (int j = 0; j < objs.length; j++) { if (j==0&&StringUtils.isNotEmpty(objs[j].getClass().getName())) { map.put("psCode"+i,objs[0].toString()); }else{ map.put("psName"+i,objs[1].toString()); } } } return map; } /** * 根据所获的的企业的PSName获取他的监控点 * @param pscode 企业代码 * @return Map<String,Object> 键值对的集合 */ @Override public Map<String, Object> findAllOutPutCode(String psCode) { //设置Long类型的变量,用于将String类型的企业代码转换为数据库中的bigint类型的数据 Long psCode1; //创建用于存储键值对的map集合 Map<String, Object> map = new HashMap<String, Object>(); //创建session对象 Session session = this.getSession(); //创建事务的对象 Transaction trans = session.beginTransaction(); //调用存储过程 SQLQuery query = session.createSQLQuery("{Call ProcYB_GetOutputInfoByPSCode(?)}"); if ("".equals(psCode)||psCode==null) { psCode1 = (long) -1; }else{ psCode1 = Long.parseLong(psCode); } //为存储过程设置输入参数 query.setLong(0,psCode1 == null ? 0 : psCode1); //提交事务 trans.commit(); //获取存储过程的运行结果(得到的结果是Object类型的数组集合)存入list集合 List list = query.list(); //循环遍历该结果集合 for (int i = 0; i < list.size(); i++) { //用Object数组类型的对象objs接收每一次外层循换得到的对象 Object[] objs = (Object[]) list.get(i); //通过内层循环取出每一个objs集合中的数据放入map集合中 for (int j = 0; j < objs.length; j++) { if (j==2&&StringUtils.isNotEmpty(objs[j].getClass().getName())) { map.put("outPutName"+i,objs[2].toString()); }else if(j==1&&StringUtils.isNotEmpty(objs[j].getClass().getName())){ map.put("outPutCode"+i,objs[1].toString()); } } } return map; }
正常运行的代码(JDBC方式:不光是dao.impl层中,而且web层中还要有类JdbcUtil.java并且要有sqljdbc4.jar包的驱动支持,还要在MANIFEST.MF文件中配置,还要在build.properties文件中配置):
Dao.impl层中的方法:
/** * 查找符合条件的排污企业放入Map集合(JDBC方式) * @return Map<String,Object> 键值对的集合 */ @Override public Map<String,Object> findAllCommunication(String userName) { //创建用于存储键值对的map集合 Map<String, Object> map = new HashMap<String, Object>(); List<Records> recordList = new ArrayList<Records>(); try { Connection dbConn = JdbcUtil.getConn(); CallableStatement statement = dbConn.prepareCall("SET NOCOUNT ON exec dbo.ProcYB_GetPSList ?"); statement.setString(1, userName==null ? "" : userName); ResultSet rs = statement.executeQuery(); while (rs.next()) { Records c = new Records(); String psCode = rs.getString("psCode"); String psName = rs.getString("psName"); c.setPsCode(psCode); c.setPsName(psName); recordList.add(c); } statement.close(); } catch (Exception e1) { e1.printStackTrace(); } if (recordList!=null&&recordList.size()>0) { for (int i = 0; i < recordList.size(); i++) { Records record = recordList.get(i); if (record!=null&&StringUtils.isNotEmpty(record.getPsCode())) { map.put("psCode"+i,record.getPsCode()); } if(record!=null&&StringUtils.isNotEmpty(record.getPsName())){ map.put("psName"+i,record.getPsName()); } } } return map; } /** * 根据所获的的企业的PSName获取他的监控点(JDBC方式) * @param pscode 企业代码 * @return Map<String,Object> 键值对的集合 */ @Override public Map<String, Object> findAllOutPutCode(String psCode) { //设置Long类型的变量,用于将String类型的企业代码转换为数据库中的bigint类型的数据 Long psCode1; //创建用于存储键值对的map集合 Map<String, Object> map = new HashMap<String, Object>(); List<Records> recordList = new ArrayList<Records>(); try { Connection dbConn = JdbcUtil.getConn(); CallableStatement statement = dbConn .prepareCall("SET NOCOUNT ON exec dbo.ProcYB_GetOutputInfoByPSCode ?"); statement.setString(1, psCode==null ? "" : psCode); ResultSet rs = statement.executeQuery(); while (rs.next()) { Records c = new Records(); String outPutCode = rs.getString("outPutCode"); String outPutName = rs.getString("outPutName"); c.setOutPutCode(outPutCode); c.setOutPutName(outPutName); recordList.add(c); } statement.close(); } catch (Exception e1) { e1.printStackTrace(); } if (recordList!=null&&recordList.size()>0) { for (int i = 0; i < recordList.size(); i++) { Records record = recordList.get(i); if (record!=null&&StringUtils.isNotEmpty(record.getOutPutCode())) { map.put("outPutCode"+i,record.getOutPutCode()); } if(record!=null&&StringUtils.isNotEmpty(record.getOutPutName())){ map.put("outPutName"+i,record.getOutPutName()); } } } return map; }
Web层中JdbcUtil.java类中的代码:
package com.jointsky.jointframe.record.management.web; import java.sql.Connection; import java.sql.DriverManager; public class JdbcUtil { public static Connection getConn() { String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; String dbURL = "jdbc:sqlserver://服务器ip:1433;SelectMethod=cursor;DatabaseName=数据源名称"; // String dbURL = "jdbc:sqlserver://localhost:1433;SelectMethod=cursor;DatabaseName=数据源名称"; String userName = "sa"; String userPwd = "1234.com"; Connection dbConn = null; try { Class.forName(driverName); dbConn = DriverManager.getConnection(dbURL, userName, userPwd); System.out.println("连接数据库成功"); } catch (Exception e) { e.printStackTrace(); System.out.print("连接失败"); } return dbConn; } }
MANIFEST.MF文件中配置:
Build.properties文件中的配置:
将sqljdbc4.jar包放入lib文件夹中,添加支持。