一个dbcp问题的解决

2019-03-26  本文已影响0人  大P还是小p

背景

最近有个项目,是在用户原有的仓储系统中集成RFID硬件。用户希望我们在他们原系统上直接开发,添加相关的几个功能模块,以节约开发成本。
原系统使用JDK8,数据库SQLServer,Dao层hiberante5,连接池dbcp,JDBC版本是4.2。

问题

在使用原生sql实现一个查询时,发生了以下错误。

Exception in thread "JavaFX Application Thread" java.lang.AbstractMethodError: Method org/apache/commons/dbcp/DelegatingResultSet.getNString(Ljava/lang/String;)Ljava/lang/String; is abstract
    at org.apache.commons.dbcp.DelegatingResultSet.getNString(DelegatingResultSet.java)
    at org.hibernate.type.descriptor.sql.NVarcharTypeDescriptor$2.doExtract(NVarcharTypeDescriptor.java:62)
    at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:260)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:256)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:252)
    at org.hibernate.loader.custom.ScalarResultColumnProcessor.extract(ScalarResultColumnProcessor.java:54)
    at org.hibernate.loader.custom.ResultRowProcessor.buildResultRow(ResultRowProcessor.java:83)
    at org.hibernate.loader.custom.ResultRowProcessor.buildResultRow(ResultRowProcessor.java:60)
    at org.hibernate.loader.custom.CustomLoader.getResultColumnOrRow(CustomLoader.java:413)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:769)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:985)
    at org.hibernate.loader.Loader.doQuery(Loader.java:943)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
    at org.hibernate.loader.Loader.doList(Loader.java:2615)
    at org.hibernate.loader.Loader.doList(Loader.java:2598)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
    at org.hibernate.loader.Loader.list(Loader.java:2425)
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2153)
    at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:987)
    at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)

分析

从错误信息分析,数据sql查询没有问题,结果集已经获得,错误发生在将结果集SQL字符串类型NVarcharType转换为String类型时,原因是dbcp.DelegatingResultSet未实现getNString()这个虚方法。

查看了一下使用的dbcp.DelegatingResultSet,确实只实现了getString()方法而并没有看到getNString()。

呃,粗略搜索了一下解决方法,好像没有人遇到相同的问题,看来是哪里用得不对。。。但看到了有人遇到dbcp关于版本以起的一些问题,想着有可能也是版本问题,当前的dbcp版本是1.3。

DelegatingResultSet看着是对ResultSet接口的实现类。于是看了一下JDK8中关于ResultSet.getNString()的说明,如下,即JDK1.6以后加入,用于转换NCHAR、NVARCHAR、LONGNVARCHAR等sql类型。

    /**
     * Retrieves the value of the designated column in the current row
     * of this <code>ResultSet</code> object as
     * a <code>String</code> in the Java programming language.
     * It is intended for use when
     * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
     * and <code>LONGNVARCHAR</code> columns.
     *
     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the label is the name of the column
     * @return the column value; if the value is SQL <code>NULL</code>, the
     * value returned is <code>null</code>
     * @exception SQLException if the columnLabel is not valid;
     * if a database access error occurs
     * or this method is called on a closed result set
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @since 1.6
     */
    String getNString(String columnLabel) throws SQLException;

上dhcp官网看了一下,1.3版本确实是有够旧了啊,release时间是2010年,并且仅适用于Java 1.4-5.0

•DBCP 2.6.0 compiles and runs under Java 8 only (JDBC 4.2)
•DBCP 2.5.0 compiles and runs under Java 8 only (JDBC 4.2)
•DBCP 2.4.0 compiles and runs under Java 7 only (JDBC 4.1)
•DBCP 1.4 compiles and runs under Java 6 only (JDBC 4)
•DBCP 1.3 compiles and runs under Java 1.4-5.0 only (JDBC 3)

最新版本是2.2.6,适配的环境是Java8及JDBC 4.2,然而,看网友的一些文章说dbcp2相比dbcp有很多差异。

解决方法

升级版本:
1)将dbcp替换成2.2.6版本,
2)commons-pool2 同步替换为commons-pool2-2.6.1.jar
3)参考https://blog.csdn.net/ahuyangdong/article/details/78554058 一文修改
修改spring配置文件,主要是包名如下:

datasource类型:org.apache.commons.dbcp.BasicDataSource->org.apache.commons.dbcp2.BasicDataSource
参数:
maxWait -> maxWaitMillis
maxActive -> maxTotal

结果

getNString()问题解决。
初步测试原业务功能未受影响。

关于几种常用数据库连接池的对比

摘自:https://blog.csdn.net/qq_31125793/article/details/51241943
1:性能方面 hikariCP>druid>tomcat-jdbc>dbcp>c3p0 。hikariCP的高性能得益于最大限度的避免锁竞争。
2:druid功能最为全面,sql拦截等功能,统计数据较为全面,具有良好的扩展性。
3:综合性能,扩展性等方面,可考虑使用druid或者hikariCP连接池。

Springboot2默认数据库连接池是HikariCP,原因:代码量少、口碑好、速度最快、稳定可靠。

上一篇下一篇

猜你喜欢

热点阅读