大道至简,知易行难
广阔天地,大有作为

DB2 IBM Data Server Driver for JDBC and SQLJ不同版本下JDBC ResultSetMetaData.getColumnName和ResultSetMetaData.getColumnLabel行为不一致的坑

近期,在某生产系统架构重构中,因故提高了其中一个工程的Mybatis的版本。受此影响,需要配合提高DB2 JDBC Driver的版本,否则由于旧版DB2 JDBC Driver没有实现JDBC4中的一个方法会报一个诡异的异常(Caused by: java.lang.AbstractMethodError: com.ibm.db2.jcc.am.to.isClosed()Z):

低版本DB2 JDBC Driver未实现JDBC4的接口

低版本DB2 JDBC Driver未实现JDBC4的接口

此前,升级DB2 JDBC Driver的操作已经在多个其他生产系统中进行过,并未遇到问题。然而,由于本次被重构生产系统A使用的是WebLogic容器提供的JNDI数据源,而该数据源还被另一个使用了原生JDBC手拼SQL的遗留系统B使用。在升级了DB2 JDBC Driver的版本至9.7.6后,发现这个使用了原生JDBC的遗留系统B出现了问题。具体是,其手拼SQL对应查询结果的HashMap中原本大小写敏感的Key变成了大写(即使使用了AS指定了别名):

出问题的代码

出问题的代码

观察到该遗留系统使用了如下的写法来处理JDBC的ResultSet:

遗留代码错误的写法片段

遗留代码错误的写法片段

怀疑是getColumnName的用法不正确。进一步搜索,可以在IBM官网上找到关于此问题的文档:

官方有关getColumnName和getColumnLabel的描述

官方有关getColumnName和getColumnLabel的描述

其中提到:

For the IBM Data Server Driver for JDBC and SQLJ version 4.0 and later, the default behavior of ResultSetMetaData.getColumnName and ResultSetMetaData.getColumnLabel differs from the default behavior for earlier JDBC drivers. You can use the useJDBC4ColumnNameAndLabelSemantics property to change this behavior.

显然,对于IBM Data Server Driver for JDBC and SQLJ version 4.0及更高版本中,使用getColumnName是不正确的,也就说DB2 IBM Data Server Driver for JDBC and SQLJ不同版本下JDBC ResultSetMetaData.getColumnName和ResultSetMetaData.getColumnLabel行为不一致。

与不正确的代码相比,我们可以看到Spring的做法是正确的:

Spring中正确的写法

Spring中正确的写法

因此,就有了三种解决方案:
1、将所有的getColumnName改为getColumnLabel,但可能需要回归测试;
2、设置useJDBC4ColumnNameAndLabelSemantics属性,但由于JNDI数据源被多个应用公用可能有影响;
3、设置useJDBC4ColumnNameAndLabelSemantics属性属性后,设置多个JNDI数据源,遗留系统自己用一个;

解决方案三选一

解决方案三选一

参考文档:
1、https://www.ibm.com/support/knowledgecenter/SSEPGG_11.1.0/com.ibm.db2.luw.apdv.java.doc/src/tpc/imjcc_c0052593.html
2、https://www.ibm.com/support/pages/tech-tip-ibm-universal-jdbc-driver-behavior-when-calling-resultsetmetadatagetcolumnname-and-getcolumnlabel-against-db2-luw-server

转载时请保留出处,违法转载追究到底:进城务工人员小梅 » DB2 IBM Data Server Driver for JDBC and SQLJ不同版本下JDBC ResultSetMetaData.getColumnName和ResultSetMetaData.getColumnLabel行为不一致的坑

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址