Заставить Spring / JPA / Hibernate / JDBC повторить неудачную транзакцию beginTransaction? - PullRequest
2 голосов
/ 14 июня 2011

Иногда транзакция БД не может начаться из-за простой SocketException при попытке достичь MySQL.В текущей кодовой базе весь код 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.Я ненавижу автоматические рамки, которые якобы решают все проблемы.Это было не мое решение сделать в этом проекте.

Ответы [ 2 ]

2 голосов
/ 14 июня 2011

Если вы не хотите вносить циклы повторов в свой код, возможно, вы можете использовать AOP для реализации функциональности повторов.Существует пример такого совета в документации Spring.

0 голосов
/ 14 июня 2011

Создайте служебный метод, который принимает TransactionCallback в качестве параметра.В этом методе выполняйте циклы и обработку исключений, используя TransactionTemplate .

Когда вам нужно выполнить запрос с повторными попытками, используйте этот метод.

См. Spring Reference для подробностей.

Например, ваш код вызова будет выглядеть так:

public Object someServiceMethod() {
  return yourUtilityObj.retry(new TransactionCallback() {

    public Object doInTransaction(TransactionStatus status) {
      updateOperation1();
      return resultOfUpdateOperation2();
    }
  });
}
...