@Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (RuntimeException ex) { // Let it throw raw if the type of the exception is on the throws clause of the method. if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) { throw ex; } else { PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator; if (translator == null) { Assert.state(this.beanFactory != null, "No PersistenceExceptionTranslator set"); translator = detectPersistenceExceptionTranslators(this.beanFactory); this.persistenceExceptionTranslator = translator; } throw DataAccessUtils.translateIfNecessary(ex, translator); } } }
@Override public void flush() { try { getEntityManagerHolder().getEntityManager().flush(); } catch (RuntimeException ex) { throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect()); } }
@Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (RuntimeException ex) { // Let it throw raw if the type of the exception is on the throws clause of the method. if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) { throw ex; } else { PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator; if (translator == null) { Assert.state(this.beanFactory != null, "No PersistenceExceptionTranslator set"); translator = detectPersistenceExceptionTranslators(this.beanFactory); this.persistenceExceptionTranslator = translator; } throw DataAccessUtils.translateIfNecessary(ex, translator); } } }
@Override public void flush() { try { getEntityManagerHolder().getEntityManager().flush(); } catch (RuntimeException ex) { throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect()); } }
@Test public void empty() { ChainedPersistenceExceptionTranslator pet = new ChainedPersistenceExceptionTranslator(); //MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator(); RuntimeException in = new RuntimeException("in"); assertSame(in, DataAccessUtils.translateIfNecessary(in, pet)); }
@Test public void exceptionTranslationWithNoTranslation() { MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator(); RuntimeException in = new RuntimeException(); assertSame(in, DataAccessUtils.translateIfNecessary(in, mpet)); }
@Override protected void doCommit(DefaultTransactionStatus status) { JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Committing JPA transaction on EntityManager [" + txObject.getEntityManagerHolder().getEntityManager() + "]"); } try { EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); tx.commit(); } catch (RollbackException ex) { if (ex.getCause() instanceof RuntimeException) { DataAccessException dae = getJpaDialect().translateExceptionIfPossible((RuntimeException) ex.getCause()); if (dae != null) { throw dae; } } throw new TransactionSystemException("Could not commit JPA transaction", ex); } catch (RuntimeException ex) { // Assumably failed to flush changes to database. throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect()); } }
@Test public void exceptionTranslationWithTranslation() { MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator(); RuntimeException in = new RuntimeException("in"); InvalidDataAccessApiUsageException out = new InvalidDataAccessApiUsageException("out"); mpet.addTranslation(in, out); assertSame(out, DataAccessUtils.translateIfNecessary(in, mpet)); }
@Override protected void doCommit(DefaultTransactionStatus status) { JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Committing JPA transaction on EntityManager [" + txObject.getEntityManagerHolder().getEntityManager() + "]"); } try { EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); tx.commit(); } catch (RollbackException ex) { if (ex.getCause() instanceof RuntimeException) { DataAccessException dae = getJpaDialect().translateExceptionIfPossible((RuntimeException) ex.getCause()); if (dae != null) { throw dae; } } throw new TransactionSystemException("Could not commit JPA transaction", ex); } catch (RuntimeException ex) { // Assumably failed to flush changes to database. throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect()); } }
@Test public void exceptionTranslationWithTranslation() { MapPersistenceExceptionTranslator mpet1 = new MapPersistenceExceptionTranslator(); RuntimeException in1 = new RuntimeException("in"); InvalidDataAccessApiUsageException out1 = new InvalidDataAccessApiUsageException("out"); InvalidDataAccessApiUsageException out2 = new InvalidDataAccessApiUsageException("out"); mpet1.addTranslation(in1, out1); ChainedPersistenceExceptionTranslator chainedPet1 = new ChainedPersistenceExceptionTranslator(); assertSame("Should not translate yet", in1, DataAccessUtils.translateIfNecessary(in1, chainedPet1)); chainedPet1.addDelegate(mpet1); assertSame("Should now translate", out1, DataAccessUtils.translateIfNecessary(in1, chainedPet1)); // Now add a new translator and verify it wins MapPersistenceExceptionTranslator mpet2 = new MapPersistenceExceptionTranslator(); mpet2.addTranslation(in1, out2); chainedPet1.addDelegate(mpet2); assertSame("Should still translate the same due to ordering", out1, DataAccessUtils.translateIfNecessary(in1, chainedPet1)); ChainedPersistenceExceptionTranslator chainedPet2 = new ChainedPersistenceExceptionTranslator(); chainedPet2.addDelegate(mpet2); chainedPet2.addDelegate(mpet1); assertSame("Should translate differently due to ordering", out2, DataAccessUtils.translateIfNecessary(in1, chainedPet2)); RuntimeException in2 = new RuntimeException("in2"); OptimisticLockingFailureException out3 = new OptimisticLockingFailureException("out2"); assertNull(chainedPet2.translateExceptionIfPossible(in2)); MapPersistenceExceptionTranslator mpet3 = new MapPersistenceExceptionTranslator(); mpet3.addTranslation(in2, out3); chainedPet2.addDelegate(mpet3); assertSame(out3, chainedPet2.translateExceptionIfPossible(in2)); }
/** * Surrounds the transaction with a try/catch block that can use the {@link PersistenceExceptionTranslator} to * translate the exception if necessary. * * @param callable The data operation to invoke. * @param <T> The type of the data operation. * * @return The result from the data operation, if successful. */ protected <T> T doWithExceptionTranslation(Callable<T> callable) { try { return callable.call(); } catch (RuntimeException ex) { throw DataAccessUtils.translateIfNecessary(ex, this.persistenceExceptionTranslator); } catch (Exception ex) { // this should really never happen based on the internal usage in this class throw new RiceRuntimeException("Unexpected checked exception during data access.", ex); } }
@Override public void flush() { try { getEntityManagerHolder().getEntityManager().flush(); } catch (RuntimeException ex) { throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect()); } }
@Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (RuntimeException ex) { // Let it throw raw if the type of the exception is on the throws clause of the method. if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) { throw ex; } else { PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator; if (translator == null) { Assert.state(this.beanFactory != null, "No PersistenceExceptionTranslator set"); translator = detectPersistenceExceptionTranslators(this.beanFactory); this.persistenceExceptionTranslator = translator; } throw DataAccessUtils.translateIfNecessary(ex, translator); } } }
@Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (RuntimeException ex) { // Let it throw raw if the type of the exception is on the throws clause of the method. if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) { throw ex; } else { PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator; if (translator == null) { Assert.state(this.beanFactory != null, "No PersistenceExceptionTranslator set"); translator = detectPersistenceExceptionTranslators(this.beanFactory); this.persistenceExceptionTranslator = translator; } throw DataAccessUtils.translateIfNecessary(ex, translator); } } }
@Override protected void doCommit(DefaultTransactionStatus status) { JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Committing JPA transaction on EntityManager [" + txObject.getEntityManagerHolder().getEntityManager() + "]"); } try { EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); tx.commit(); } catch (RollbackException ex) { if (ex.getCause() instanceof RuntimeException) { DataAccessException dae = getJpaDialect().translateExceptionIfPossible((RuntimeException) ex.getCause()); if (dae != null) { throw dae; } } throw new TransactionSystemException("Could not commit JPA transaction", ex); } catch (RuntimeException ex) { // Assumably failed to flush changes to database. throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect()); } }