2015-08-24 2 views
1

Я получаю UnexpectedRollbackException в моем приложении весной. Вот мой Repository классКак обрабатывать UnexpectedRollbackException?

@Repository 
public class MyDao { 

    @PersistenceContext 
    EntityManager em; 

    public MyData save(MyData myData){ 
     return em.merge(myData) 
    } 
} 

Вот мой сервис класс

@Service 
public class MyService{ 
    @Autowired 
    Mydao myDao; 

    @Transactional 
    public void saveMyData(MyData myData){ 
     myDao.save(myData); 
    } 
} 

Здесь я звоню метод службы.

@Component 
public class ScheduledService{ 

    @Autowired 
    MyService myService; 

    @Scheduled(fixedDelay=60000) 
    public void myDataScheduler(){ 
     // ... create mydata object 
     for(int i = 0; i < 5; i++) 
      myService.saveMyData(myData); 
    } 
} 

MyData имеет некоторые ограничения, так что я ожидал ConstraintViolationException. Все, что мне нужно сделать, - это если выкинуть ConstraintViolationException, провалиться тихо. Поскольку в методе службы нет другой операции с БД, я думаю, мне не нужен откат здесь. Но я получаю следующее исключение, когда ограничение нарушает. Что я здесь делаю неправильно?

2015-08-24 18:01:28,677 SEVERE [org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler] (pool-5-thread-1) Unexpected error occurred in scheduled task.: org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction. 
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1024) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at com.myapp.service.saveMyData() [spring-core-4.1.6.RELEASE.jar:] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_75] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_75] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_75] 
    at java.lang.reflect.Method.invoke(Method.java:606) [rt.jar:1.7.0_75] 
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) [spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_75] 
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) [rt.jar:1.7.0_75] 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178) [rt.jar:1.7.0_75] 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [rt.jar:1.7.0_75] 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_75] 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_75] 
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_75] 
Caused by: javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction. 
    at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1178) 
    at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126) 
    at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75) 
    at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:173) 
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1021) [spring-tx-4.0.7.RELEASE.jar:4.0.7.RELEASE] 
    ... 24 more 
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1882) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:119) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:50) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76) 
    at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:358) 
    at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:91) 
    at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162) 
    at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1166) 
    ... 28 more 
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:114) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    ... 34 more 
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (IM.UK_K4P6Q9JG3ANIQKAWWAI65TWX5) violated 

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399) 
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059) 
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522) 
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) 
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587) 
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225) 
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53) 
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:943) 
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1150) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4875) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1361) 
    at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    ... 45 more 
+0

Я думаю, у вас уже есть запись для уникального ограничения, и попытка сохранить другой вызывает «SQLIntegrityConstraintViolationException», и поскольку ваш метод обслуживания в качестве аннотации «@ Transactional» вызывает другие исключения, которые являются «UnexpectedRollbackException» и «RollBackException» '. Если вы хотите, чтобы «SQLIntegrityConstraintViolationException» удаляло аннотацию '@ Transactional', но больше не будет отката, и это может быть очень плохо. – Deh

+0

Начальные стопоры перестают смешивать различные версии пружин ... В настоящее время вы смешиваете 4.0.7 и 4.1.6, что, как правило, плохое. Затем вы нарушаете уникальное ограничение, поэтому поле должно быть уникальным, а это не так. –

+0

Ваша трассировка стека говорит 'Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: уникальное ограничение (IM.UK_K4P6Q9JG3ANIQKAWWAI65TWX5) нарушило ', что ясно говорит вам, что основная причина для' UnexpectedRollbackException' является нарушением одного из ваших уникальных ограничений. Это то, чего вы ожидали. – DrunkenPope

ответ

0

То, как я разработал поток, действительно был очень плохим.

Я переработал поток. Прежде чем пытаться вставить объект в БД, я делаю запрос выбора на основе ограничений. Если запрос находит какие-либо объекты, я выбрасываю специальное исключение DataAlreadyExistsException. В противном случае я делаю вставку.

Это решило мою проблему. Спасибо всем, кто помог мне разобраться с решением.

1

«Все, что мне нужно сделать, это, если ConstraintViolationException брошено, не в состоянии молча. Поскольку нет никаких других операций DB внутри метода службы, я думаю, мне не нужно откатить здесь.»

Это то, что Весна не знает, пока вы не проинструктируете об этом. То, что вы испытываете это:

  • вы начать транзакцию
  • вы выполнить операцию DB
  • ваша операция DB терпит неудачу (и вы с этим согласны)
  • Как ожидаемое исключение (ConstraintViolation) на самом деле не ожидалось (вы его не обрабатывали) он достигает точки завершения транзакции
  • В этот момент Весна предполагает, что вся транзакция должна быть отброшена.

Следовательно, Неожиданное исключение RollbackException. Чтобы предотвратить это, вам нужно всего лишь поймать (и проглотить, если вы действительно хотите проигнорировать эту проблему) оригинал ConstraintViolationException ВМЕСТЕ С транзакцией. Внутри saveMyData(), например, было бы хорошо.

+2

В зависимости от вашей установки есть большие изменения, которые не будут работать. Hibernate только отправит SQL на сервер, если это действительно нужно. В этом случае он уже пытается зафиксировать данные, что приводит к потере SQL в базу данных. В этот момент он потерпит неудачу. Захват исключения внутри этого метода будет довольно бессмысленным, поскольку исключение возникает после выполнения метода. –

+0

Поскольку я не очищаю данные в DAO, в этом случае cathcing 'ConstraintViolationException' в транзакции не будет полезен. – Nayan