美文网首页
一个dbcp问题的解决

一个dbcp问题的解决

作者: 大P还是小p | 来源:发表于2019-03-26 21:30 被阅读0次

    背景

    最近有个项目,是在用户原有的仓储系统中集成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,原因:代码量少、口碑好、速度最快、稳定可靠。

    相关文章

      网友评论

          本文标题:一个dbcp问题的解决

          本文链接:https://www.haomeiwen.com/subject/enenvqtx.html