Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force Spring/JPA/Hibernate/JDBC to retry a failed beginTransaction?

Sometimes a db transaction can't begin because of a simple SocketException when trying to reach MySQL. In the current codebase, all SQL or JPQL code resides in classes with the @Transactional annotation (org.springframework.transaction.annotation). A transaction is created for me for each method call to an annotated class. This makes it difficult to write code that can be reused across all db calls.

One solution would be to put the db code within a loop: It will retry the transaction a few times. This works but I'd prefer not to sprinkle my code full of loops (one for each db call).

Is their a way to make either one of the following frameworks retry a failed beginTransaction automatically?: Spring, JPA, Hibernate, c3p0, MySQL JDBC driver

For reference, here is a piece of the log:

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. I hate automagic frameworks that supposedly solve all problems. It wasn't my decision to make in this project.

like image 652
Arne Evertsson Avatar asked Oct 27 '25 13:10

Arne Evertsson


1 Answers

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.

like image 79
axtavt Avatar answered Oct 30 '25 03:10

axtavt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!