如何从Spring $$ EnhancerBySpringCGLIB $$中捕获异常?

问题描述:

我有和this人一样的问题。我得到的堆栈跟踪,由于这样的事实,我把那违反了约束的独特领域的一个新纪录:

Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement 
at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:241) 
at org.springframework.orm.hibernate5.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:755) 
at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:594) 
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) 
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) 
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504) 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) 
at sistema.database.manager.BookManager$$EnhancerBySpringCGLIB$$d46d6805.create(<generated>) 
at tests.unatantum.migration.InactiveBookMigration.migrate(InactiveBookMigration.java:53) 
at tests.unatantum.migration.InactiveBookMigration.main(InactiveBookMigration.java:42) 

当我把这个方法(在管理者),它有一个通用的变量T和@Transactional放入整个类,而不是在每一个方法:

public void create(T value) { 
    try{ 
     System.out.println(value); 
     getDao().create(value); 
     System.out.println("good"); 
    } catch (DataIntegrityViolationException dive){ 
     throw new SistemaRuntimeException(dive.getMessage() + ": " + value); 
    } 
} 

System.out.println只是用于调试的原因。
问题是我希望能够直接在管理器中捕获该异常。但在堆栈跟踪中,只有未知类似乎工作。我怎样才能在管理者中捕获异常(如果可能的话,采用同样的方法)?
它似乎抛出异常,当它提交的方法调用所示的一个(这是在同一个经理)的末尾提交。在我打电话给Dao之前,我真的需要把这张支票放进去吗?这不是让我浪费时间,而是应该能够等待异常吗?

我认为这个行为与事务拦截器有关。如果你把@Transactional的类,春创建了一个动态代理(经理的子类)和基本调用看起来像

create(t) -> proxy.handle(methodCall) -> open transaction -> call real method (your manager.create(..), where the catch block is) -> commit transaction (this is where the exception happens) -> return result from proxy.create(t)

所以BookManager$$EnhancerBySpringCGLIB$$d46d6805是在此之前和之后,您的方法调用增加了行为的子类。捕获发生在你的方法调用中。并且在提交时发生异常。因此,异常发生在代理之外,在你的捕获之外。 如果你想捕获这个异常,你需要确保事务在你离开你的catch块之前被提交(例如,通过在自己的事务中执行dao.create(..)来执行)。