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

时间:2017-02-09 13:44:30

标签: java spring exception-handling

我和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之前是否真的需要检查,是否因为我应该等待异常而浪费时间?

1 个答案:

答案 0 :(得分:2)

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

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(..)在其自己的事务中执行)。