强制 Spring/JPA/Hibernate/JDBC 重试失败的 beginTransaction?
有时,在尝试访问 MySQL 时,数据库事务会因为简单的 SocketException 而无法开始。在当前的代码库中,所有 SQL 或 JPQL 代码都驻留在带有 @Transactional 注释(org.springframework.transaction.annotation)的类中。为我创建一个事务,用于对带注释的类的每个方法调用。这使得编写可在所有数据库调用中重用的代码变得困难。
一种解决方案是将数据库代码放在循环中:它将重试事务几次。这是可行的,但我不想让我的代码充满循环(每个数据库调用一个)。
他们是让以下框架之一自动重试失败的 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。我讨厌据说可以解决所有问题的自动框架。在这个项目中这不是我做出的决定。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您不想在代码中引入重试循环,也许您可以使用 AOP 来实现重试功能。有一个 Spring 文档中此类建议的示例。
If you don't want to bring retry loops into your code, perhaps you can use AOP to implement retry functionality. There is an example of such an advice in Spring documentation.
创建一个实用程序方法,该方法采用 TransactionCallback 作为参数。在该方法中,使用 交易模板。
当您需要重试运行查询时,请使用此方法。
请参阅 Spring 参考细节。
例如,您的调用代码如下所示:
Create a utility method that takes a TransactionCallback as a parameter. In that method do the looping and exception handling, using a TransactionTemplate.
When you need to run a query with retries use this method.
See the Spring Reference for details.
For example, your calling code would look like: