【发布时间】:2016-06-03 21:22:39
【问题描述】:
将 Spring JdbcTemplate 与 HikariCP 和 JTDS 一起使用,以我正在维护的旧代码中连接到 MS SQL Server 数据库。我正在尝试处理应用程序已启动的情况,后来无论出于何种原因数据库变得不可用并引发连接异常。
我已经有一个自定义的 SQL 错误代码转换器(如下),它可以捕获 jdbcTemplate 引发的许多其他异常。但是连接被拒绝的异常没有被捕获,即使它被封装为 java.sql.SQLException (请参阅堆栈跟踪)。
为什么翻译器没有捕捉到这个异常?
public class CustomSqlErrorCodeTranslator extends
SQLErrorCodeSQLExceptionTranslator {
private final Log log = LogFactory.getLog(getClass());
@Override
protected DataAccessException customTranslate
(String task, String sql, SQLException sqlException) {
/*
* We want to capture all codes.
*/
StringBuilder logMsg = new StringBuilder("*********************SQL Exception:");
logMsg.append(", errorCode: " + sqlException.getErrorCode())
.append(", message: " + sqlException.getMessage())
;
log.error(logMsg.toString());
return null;
}
}
public class Dao {
//HikariDataSource dataSource;
DataSource dataSource;
protected JdbcTemplate jdbcTemplate;
private final Log log = LogFactory.getLog(getClass());
private boolean connected = false;
private CustomSqlErrorCodeTranslator exceptionHandler;
public void setDataSource(DataSource ds) {
//this.jdbcTemplate = new JdbcTemplate(ds);
try {
this.jdbcTemplate = new JdbcTemplate(ds);
exceptionHandler = new CustomSqlErrorCodeTranslator();
this.jdbcTemplate.setExceptionTranslator(exceptionHandler);
connected = true;
} catch (Exception e) {
if (e.getCause() != null && e.getCause() instanceof SQLException) {
log.error("******Cannot connect to database.***************************");
log.debug(e.getMessage());
}
}
}
}
16:59:33,542 [main] WARN PoolBase - springHikariCP - Connection net.sourceforge.jtds.jdbc.JtdsConnection@42206bce failed alive test with exception I/O Error: Connection reset by peer: socket write error
16:59:33,542 [Hikari connection closer (pool springHikariCP)] DEBUG PoolBase - springHikariCP - Closing connection net.sourceforge.jtds.jdbc.JtdsConnection@42206bce: (connection evicted or dead)
16:59:34,530 [main] DEBUG HikariPool - Timeout failure pool springHikariCP stats (total=0, active=0, idle=0, waiting=0)
16:59:34,544 [Hikari connection adder (pool springHikariCP)] DEBUG HikariPool - springHikariCP - Cannot acquire connection from data source
java.sql.SQLException: Network error IOException: Connection refused: connect
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:436)
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:101)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:314)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:171)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:436)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:65)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:567)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:560)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at net.sourceforge.jtds.jdbc.SharedSocket.createSocketForJDBC3(SharedSocket.java:288)
at net.sourceforge.jtds.jdbc.SharedSocket.<init>(SharedSocket.java:251)
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:331)
... 13 more
16:59:35,746 [Hikari connection adder (pool springHikariCP)] DEBUG HikariPool - springHikariCP - Cannot acquire connection from data source
java.sql.SQLException: Network error IOException: Connection refused: connect
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:436)
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:101)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:314)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:171)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:436)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:65)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:567)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:560)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at net.sourceforge.jtds.jdbc.SharedSocket.createSocketForJDBC3(SharedSocket.java:288)
at net.sourceforge.jtds.jdbc.SharedSocket.<init>(SharedSocket.java:251)
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:331)
... 13 more
16:59:37,010 [Hikari connection adder (pool springHikariCP)] DEBUG HikariPool - springHikariCP - Cannot acquire connection from data source
很抱歉,我花了这么长时间才意识到我需要添加到堆栈跟踪中。
这是我停止数据库时的堆栈跟踪。现在很清楚,涉及到 JDBC 模板。如果涉及 JdbcTemplate,在我看来,自定义异常处理程序应该接受它。有没有其他人有使用自定义错误代码翻译器捕获数据库连接异常的经验?
5:06:05,076 [ActiveMQ Session Task-1] DEBUG HikariPool - Timeout failure pool HikariPool-0 stats (total=1, active=1, idle=0, waiting=2)
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-0 - Connection is not available, request timed out after 10000ms.
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:615)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:866)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:927)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:937)
at com.pevco.persist.resources.AvailabilityDaoImpl.create(AvailabilityDaoImpl.java:51)
at com.pevco.nexgen.health.handlers.SystemModelListener.onMessage(SystemModelListener.java:135)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:746)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:684)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651)
at org.springframework.jms.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:622)
at org.springframework.jms.listener.SimpleMessageListenerContainer.processMessage(SimpleMessageListenerContainer.java:330)
at org.springframework.jms.listener.SimpleMessageListenerContainer$2.onMessage(SimpleMessageListenerContainer.java:306)
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1321)
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:129)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:47)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.sql.SQLTransientConnectionException: HikariPool-0 - Connection is not available, request timed out after 10000ms.
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:195)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:147)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
... 20 more
Caused by: java.sql.SQLException: Network error IOException: Connection refused: connect
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:436)
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:314)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:171)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:436)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:65)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:567)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:560)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 3 more
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at net.sourceforge.jtds.jdbc.SharedSocket.createSocketForJDBC3(SharedSocket.java:288)
at net.sourceforge.jtds.jdbc.SharedSocket.<init>(SharedSocket.java:251)
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:331)
... 12 more
15:06:06,217 [ActiveMQ Session Task-1] DEBUG HikariPool - Timeout failure pool HikariPool-0 stats (total=1, active=1, idle=0, waiting=2)
15:06:06,217 [ActiveMQ Session Task-1] WARN SimpleMessageListenerContainer - Execution of JMS message listener failed, and no ErrorHandler has been set.
(我会在时间到期之前奖励赏金,但希望得到准确的答案。)
【问题讨论】:
-
您是否将翻译器设置为 JdbcTemplate ?
-
是的。我在发生这种情况的地方添加了道代码。当前代码检查 SqlException 的实例,但我也尝试过不使用任何 if 语句,当错误是数据库连接错误时,它仍然没有命中 catch 子句。我可以通过从表中删除一列来触发 catch 块。所以翻译器正在为其他 SqlExceptions 工作,而不是为未连接的数据库。
-
可能错误是因为 hakiri os 试图重新连接。而不是因为你的模板有问题。
-
Hikari 在指定的时间内尝试重新连接,当前设置为 1 秒。如果超时,则会引发数据库连接错误,该错误会被 jdbc 模板捕获并作为 SqlException 重新引发。但是,异常翻译器不会捕获此异常。如果其他人在使用翻译器,我想知道如何捕获数据库连接错误和翻译器。
-
在日志中我看不到模板涉及的位置。我认为它没有通过模板。模板不询问连接。它是由 hikari 制作的
标签: spring spring-jdbc hikaricp