java.lang.AbstractMethodError:在 org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setCharacter

Posted

技术标签:

【中文标题】java.lang.AbstractMethodError:在 org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setCharacterStream(DelegatingPreparedStatement.java:328)【英文标题】:java.lang.AbstractMethodError: at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setCharacterStream(DelegatingPreparedStatement.java:328) 【发布时间】:2013-08-15 05:33:02 【问题描述】:

我有一个非常讨厌的问题,我似乎无法在任何地方找到答案。

我的应用程序在尝试持久化 @Lob 时抛出此异常:

java.lang.AbstractMethodError
 at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setCharacterStream(DelegatingPreparedStatement.java:328)
 at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setCharacterStream(DelegatingPreparedStatement.java:328)
 at java.lang.reflect.Method.invoke(Method.java:601)
 at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
 at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
 at $Proxy32.setCharacterStream(Unknown Source)
 at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$3$1.doBind(ClobTypeDescriptor.java:83)
 at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:92)
 at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:280)
 at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:275)
 at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:57)
 at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2747)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3152)
 at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3087)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3416)
 at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
 at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
 at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
 at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:276)
 at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
 at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
 at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
 at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
 at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
 ...(more)

我在 Tomcat 6.0.36 上运行(也尝试过 Tomcat 7)。

mysql 4.1.22 数据库。

代码使用 jdk 7 编译并使用 gradle 构建。

我的依赖是:

+--- javax.mail:mail:1.4 -> 1.4.1
|    \--- javax.activation:activation:1.1
+--- org.slf4j:slf4j-api:1.5.6 -> 1.6.1
+--- log4j:log4j:1.2.13 -> 1.2.16
+--- org.apache.wicket:wicket:1.4.15
|    \--- org.slf4j:slf4j-api:1.5.8 -> 1.6.1
+--- org.apache.wicket:wicket-extensions:1.4.15
|    +--- org.apache.wicket:wicket:1.4.15 (*)
|    \--- org.slf4j:slf4j-api:1.5.8 -> 1.6.1
+--- mysql:mysql-connector-java:5.1.26
+--- com.microsoft.sqlserver:sqljdbc4:4.0
+--- com.itextpdf:itextpdf:5.4.2
+--- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final -> 1.0.1.Final
+--- org.hibernate:hibernate-core:4.1.9.Final
|    +--- antlr:antlr:2.7.7
|    +--- org.jboss.logging:jboss-logging:3.1.0.GA
|    +--- org.javassist:javassist:3.17.1-GA
|    +--- org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:1.0.0.Final
|    +--- dom4j:dom4j:1.6.1
|    |    \--- xml-apis:xml-apis:1.0.b2
|    +--- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final
|    \--- org.hibernate.common:hibernate-commons-annotations:4.0.1.Final
|         \--- org.jboss.logging:jboss-logging:3.1.0.CR2 -> 3.1.0.GA
+--- org.hibernate:hibernate-entitymanager:4.1.9.Final
|    +--- org.jboss.logging:jboss-logging:3.1.0.GA
|    +--- org.javassist:javassist:3.17.1-GA
|    +--- org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:1.0.0.Final
|    +--- dom4j:dom4j:1.6.1 (*)
|    +--- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final
|    +--- org.hibernate:hibernate-core:4.1.9.Final (*)
|    \--- org.hibernate.common:hibernate-commons-annotations:4.0.1.Final (*)
+--- foo.bar.data-services:foor-bar-data:2.0.0.275
|    +--- org.slf4j:slf4j-api:1.6.1
|    +--- org.hibernate:hibernate-core:4.1.6.Final -> 4.1.9.Final (*)
|    +--- org.hibernate.javax.persistence:hibernate-jpa-2.0-api::1.0.1.Final -> 1.0.1.Final
|    +--- org.slf4j:slf4j-log4j12:1.6.1
|    |    +--- org.slf4j:slf4j-api:1.6.1
|    |    \--- log4j:log4j:1.2.16
|    +--- log4j:log4j:1.2.16
|    \--- commons-configuration:commons-configuration:1.9
|         +--- commons-lang:commons-lang:2.6
|         \--- commons-logging:commons-logging:1.1.1
+--- javax.transaction:jta:1.1
+--- dom4j:dom4j:1.6.1 (*)
+--- antlr:antlr:2.7.6 -> 2.7.7
+--- commons-collections:commons-collections:3.2.1
+--- commons-configuration:commons-configuration:1.9 (*)
+--- commons-dbcp:commons-dbcp:1.4
|    \--- commons-pool:commons-pool:1.5.4 -> 1.5.7
+--- commons-pool:commons-pool:1.5.7
+--- commons-logging:commons-logging:1.1.1
+--- commons-dbutils:commons-dbutils:1.4
+--- commons-lang:commons-lang:2.6
+--- commons-io:commons-io:2.4
+--- org.apache.commons:commons-email:1.2
|    +--- javax.mail:mail:1.4.1 (*)
|    \--- javax.activation:activation:1.1
+--- javax.servlet:servlet-api:2.5
+--- javax.servlet.jsp:jsp-api:2.1
\--- org.slf4j:slf4j-log4j12:1.5.6 -> 1.6.1 (*)

所以查看异常,似乎应用程序正在尝试调用 CATALINA_BASE/lib 文件夹中的 tomcat-dbcp.jar。但我希望它在我的类路径中调用我的 commons-dbcp.jar。

但坦率地说,我很茫然,我尝试了很多东西,但似乎无法让这个工作...... 在此先感谢您的帮助。如果您需要更多信息,请告诉我。

编辑 1:

服务器.xml

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">

    <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
    <Listener className="org.apache.catalina.core.JasperListener"/>
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
    <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"/>
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>

    <GlobalNamingResources>
        <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
        <Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" logAbandoned="true" maxActive="100" maxIdle="10" maxWait="10000" name="jdbc/foo" removeAbandoned="true" removeAbandonedTimeout="300" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/foo?autoReconnect=true&amp;dumpQueriesOnException=true" username="root" validationQuery="select 1"/>     
        <Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" logAbandoned="true" maxActive="20" maxIdle="5" maxWait="10000" name="jdbc/bar" removeAbandoned="true" removeAbandonedTimeout="300" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/bar?autoReconnect=true&amp;dumpQueriesOnException=true" username="root" validationQuery="select 1"/>
    </GlobalNamingResources>

    <Service name="Catalina">
        <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>

        <Engine defaultHost="localhost" name="Catalina">
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
            <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
            <Context docBase="foo" path="/foo" reloadable="true" source="org.eclipse.jst.j2ee.server:foo"/></Host>
        </Engine>
    </Service>
</Server>

【问题讨论】:

【参考方案1】:

有同样的问题并通过更改驱动程序库解决。 DelegatingPreparedStatement 的实现将 setCharacterStream 调用委托给它的委托,这就是为什么更改驱动程序的实现可以解决问题(如果委托的实现包含该方法)

【讨论】:

【参考方案2】:

解决方案是使用 tomcat 7。它有一个 tomcat-dbcp.jar 版本,实际上具有应用程序所需的 DelegatingPreparedStatement.setCharacterStream。

我的问题是,当我在我的 tomcat 7 服务器上尝试它时,我仍然在我的应用程序的同一位置遇到相同的错误。这是由旧版本的 mysql-connector-java(如果我没记错的话是 5.0.5)由于早期尝试使其工作而在我的 tomcat lib 文件夹中挥之不去的版本引起的。这个旧版本显然优先于我作为依赖项拥有的我自己的 mysql-connector-java(最新版本)。因为这给了我同样的例外,所以它似乎并没有改变我的情况,而实际上它确实改变了。

当我弄清楚这一点时,剩下的就很简单了,我唯一的问题是我不能很容易地升级到 tomcat 7,因为其他应用程序目前正在生产环境中运行在我们的 tomcat 6 版本上。所以解决方案是将 tomcat-dbcp.jar 从 tomcat 7 dist 复制到我们的 tomcat 6 服务器并替换已经存在的那个。

希望这对其他人也有帮助,感谢大家在任何情况下的所有帮助!

【讨论】:

对我来说,修复是将公共库更新到版本 1.4:commons.dbcp.version>1.4 问题是我们想让tomcat管理所有的DB连接,所以我们没有用commons.dbcp,而是用tomcat-dbcp代替 @lugte098 这是一个非常有用的解决方案 很高兴它帮助了我以外的其他人 @tibi 谢谢你的建议,它也解决了我的问题。【参考方案3】:

我也遇到了这个问题,发现了这个问题。我在最后一个答案中接受了建议,但我没有复制 tomcat-dbcp.jar,而是在我的 pom.xml 中切换到新版本并且它可以工作!感谢您的建议!

【讨论】:

什么新版本? mysql 连接器? 啊,新版tomcat-dbcp.jar 老实说还没有真正尝试过,我会检查这是否也解决了我们的问题。这显然是从 repo 中提取依赖项的更好的解决方案,而不是在 tomcat lib 文件夹中物理地拥有更新版本。当我有时间测试这个时,我会告诉你结果。【参考方案4】:

AbstractMethodError 是 LinkageError 的子类,几乎总是表明您的类路径有问题 - 未一起编译的库正在一起加载。

假设您的库版本符合我的瞬时研究...

引发异常的行是DelegatingPreparedStatement:328。它看起来像这样:

((PreparedStatement)_stmt).setCharacterStream(parameterIndex, reader, length);

如果您点击进入setCharacterStream,您会看到它被标记为@since 1.6

所以,你应该:

    确保您在 1.6+ VM 下运行。 :)

    检查您的类路径中是否没有其他java.sql.PreparedStatement 的实现。我通常这样做的方式(在类 Unix 系统中;你自己使用 Windows;)是:

    cd /path/to/my/jars

    grep -rli 'java/sql/PreparedStatement' .

这是一种确定哪些 jar 包含哪些类的蛮力方法。它之所以有效,是因为 ZIP 文件的“目录结构”是纯文本,而不是压缩的。

祝你好运! :)

【讨论】:

感谢您提供的信息,它给了我一些寻找解决方案的新视角。【参考方案5】:

我不确定,但如果您使用最新驱动程序进行了更改

【讨论】:

我正在使用 mysql-connector-java 5.1.26,这是根据 oracle 的最新版本。有问题吗? 这个已经是最新的文件了,可以分享一下你的tomcat server.xml文件吗?

以上是关于java.lang.AbstractMethodError:在 org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setCharacter的主要内容,如果未能解决你的问题,请参考以下文章