如何解决强制Spring / JPA / Hibernate / JDBC重试失败的beginTransaction?
| 有时,由于尝试到达MySQL时会发生简单的SocketException,因此无法开始数据库事务。在当前代码库中,所有SQL或JPQL代码都位于带有@Transactional批注(org.springframework.transaction.annotation)的类中。对于为带注释的类的每个方法调用,都会为我创建一个事务。这使得很难编写可在所有数据库调用之间重用的代码。 一种解决方案是将db代码放在一个循环中:它将重试该事务几次。这行得通,但我不想让代码充满循环(每个数据库调用一个)。 他们是否有办法使以下任一框架自动重试失败的beginTransaction ?: Spring,JPA,Hibernate,c3p0,MySQL JDBC驱动程序 供参考,以下是部分日志:java.net.SocketException
MESSAGE: Connection reset
STACKTRACE:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:113)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:160)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:188)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1910)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
at com.mysql.jdbc.Connection.setAutoCommit(Connection.java:5273)
at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:881)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:91)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1353)
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:38)
at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:70)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:52)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:330)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:374)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:263)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
PS。我讨厌应该解决所有问题的自动框架。这不是我决定参与这个项目的决定。
解决方法
如果您不想在代码中引入重试循环,则可以使用AOP来实现重试功能。 Spring文档中有一个此类建议的示例。
, 创建一个将TransactionCallback作为参数的实用程序方法。在该方法中,使用TransactionTemplate进行循环和异常处理。
当您需要使用重试运行查询时,请使用此方法。
有关详细信息,请参见Spring Reference。
例如,您的调用代码如下所示:
public Object someServiceMethod() {
return yourUtilityObj.retry(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
updateOperation1();
return resultOfUpdateOperation2();
}
});
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。