Tomcat 8 上 jTDS JDBC 驱动程序的 AbstractMethodError
Posted
技术标签:
【中文标题】Tomcat 8 上 jTDS JDBC 驱动程序的 AbstractMethodError【英文标题】:AbstractMethodError with jTDS JDBC Driver on Tomcat 8 【发布时间】:2017-05-05 01:05:33 【问题描述】:我正在将 Web 应用程序 (WAR) 部署到 Tomcat 8 Web 容器。
WAR 在 '/WEB-INF/lib' 目录中包含以下 jTDS JDBC 驱动程序:
<dependency org="net.sourceforge.jtds" name="jtds" rev="1.3.1" />
(文件为:jtds-1.3.1.jar
)。
这是META-INF/context.xml
中定义资源的方式:
<Resource name="jdbc/jtds/sybase/somedb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sybase://localhost:2501/somedb"
username="someuser" password="somepassword"
/>
在我的代码中,我以正常方式获得javax.sql.DataSource:
InitialContext cxt = new InitialContext();
if ( cxt == null )
throw new RuntimeException("Uh oh -- no context!");
DataSource ds = (DataSource) cxt.lookup( lookupName );
我进一步验证(通过打印)DataSource 对象ds
是预期的类型:
org.apache.tomcat.dbcp.dbcp2.BasicDataSource
…但是当我尝试从中获得连接时:
Connection conn = ds.getConnection();
…我得到以下跟踪:
java.lang.AbstractMethodError
net.sourceforge.jtds.jdbc.JtdsConnection.isValid(JtdsConnection.java:2833)
org.apache.tomcat.dbcp.dbcp2.DelegatingConnection.isValid(DelegatingConnection.java:924)
org.apache.tomcat.dbcp.dbcp2.PoolableConnection.validate(PoolableConnection.java:282)
org.apache.tomcat.dbcp.dbcp2.PoolableConnectionFactory.validateConnection(PoolableConnectionFactory.java:359)
org.apache.tomcat.dbcp.dbcp2.BasicDataSource.validateConnectionFactory(BasicDataSource.java:2316)
org.apache.tomcat.dbcp.dbcp2.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:2299)
org.apache.tomcat.dbcp.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:2043)
org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1543)
什么给了?
【问题讨论】:
【参考方案1】:原来我必须补充:
validationQuery="select 1"
在context.xml
的资源声明中。
提到了here(尽管拼写错误为validateQuery
)。
深入了解JtdsConnection
的实现,一看便知:
/* (non-Javadoc)
* @see java.sql.Connection#isValid(int)
*/
public boolean isValid(int timeout) throws SQLException
// TODO Auto-generated method stub
throw new AbstractMethodError();
这真的很奇怪,我认为AbstractMethodError 应该只由编译器抛出,未实现的方法应该抛出UnsupportedOperationException。无论如何,来自PoolableConnection 的以下代码说明了为什么context.xml
中的validationQuery
的存在与否可以改变事情。您的 validationQuery
在以下方法中作为 sql
String
参数的值传递(如果您未定义 validationQuery
,则为 null
):
public void More ...validate(String sql, int timeout) throws SQLException
...
if (sql == null || sql.length() == 0)
...
if (!isValid(timeout))
throw new SQLException("isValid() returned false");
return;
...
所以基本上如果没有validationQuery
存在,那么会咨询连接自己的isValid
实现,在JtdsConnection
的情况下会奇怪地抛出AbstractMethodError
。
【讨论】:
我可以在 Tomcat 7/Windows 上运行该应用程序,驱动程序 1.2.8 没有问题。当我将应用程序迁移到 Docker/Linux 环境时,我遇到了这个错误。将validationQuery
添加到驱动程序的conf中解决了这个问题。【参考方案2】:
以上答案有效。如果要为独立 Java 应用程序设置它,请在数据源中设置验证查询。
BasicDataSource ds = new BasicDataSource();
ds.setUsername(user);
ds.setPassword(getPassword());
ds.setUrl(jdbcUrl);
ds.setDriverClassName(driver);
ds.setMaxTotal(10);
ds.setValidationQuery("select 1"); //DBCP throws error without this query
【讨论】:
【参考方案3】:当我遇到这个问题时,Marcus 上面提到的答案对我有用。举一个具体的例子来说明 validationQuery 设置在 context.xml 文件中的外观:
<Resource name="jdbc/myDB" auth="Container" type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://SQLSERVER01:1433/mydbname;instance=MYDBINSTANCE"
username="dbuserid" password="dbpassword"
validationQuery="select 1"
/>
validationQuery 设置与您的数据库连接的每个驱动程序设置一起使用。因此,每次向 context.xml 文件添加另一个 db 条目时,都需要将此设置包含在驱动程序设置中。
【讨论】:
以上是关于Tomcat 8 上 jTDS JDBC 驱动程序的 AbstractMethodError的主要内容,如果未能解决你的问题,请参考以下文章
SqlClient/OLEDB 驱动程序的连接字符串,如 jdbc:jtds 驱动程序?
ms sql microsoft的jdbc驱动和jTDS的驱动的区别
使用 JDBC 的 SQL Server 连接 - JTDS
通过 JTDS 驱动程序执行 SQL Server 调用时出现“第 24 行位置的 JDBC 转义语法无效 '=' 预期字符”错误的原因?