noRollbackFor 并不总是处理未经检查的异常(不是重复的)
noRollbackFor not always working on unchecked exceptions (not a duplicate)
我见过很多类似的问题,但它们通常与我的问题无关。
这是我的代码。
@Override //class implements interface
//can also add "rollbackFor = OutOfMemoryError.class" here, to no avail
@Transactional(noRollbackFor = IllegalArgumentException.class)
public ReportTemplate getByCode(final String code)
//throws IllegalArgumentException - see question text
{
if(code == null) {
throw new IllegalArgumentException("ss");
}
}
消费者(非事务性)通过自动装配接口调用此方法。
尽管 noRollbackFor 事务(仅由此方法组成)被回滚。
好的,我理解那些说 "by default it's rollbackFor any unchecked, so since the default is not overridden, that rule still applies" 的人。但这不应该是真的,因为那意味着 noRollbackFor 是无用的:)我们可以尝试像上面的评论中那样指定 rollbackFor,希望它会取消 "default" rollbackFor - 但这无济于事:回滚仍然发生;看起来这个设置只是添加到 "default"。最糟糕的是,当 noRollbackFor 和 rollbackFor 覆盖相同的后代异常时,我找不到关于它应该如何工作的精确规范(比如在我的例子中,RuntimeException vs IllegalArgumentException,谁赢了?)。
好吧,我找到了 but one official clarification,上面写着 "the strongest matching rule wins" - 但这似乎不是普遍正确的,就像我的情况一样。此外,出于某种原因,它们过于具体:他们说 no-rollback-for="InstrumentNotFoundException" 意味着,从字面上看,"any exception other than an InstrumentNotFoundException" 将被回滚(但是 InstrumentNotFoundException 的后代呢?)而且无论如何它已经过时了: 2.5.x,而较新的文档只是以一种相当矛盾的方式说了类似 "rollbackFor lists exceptions to be rolled back, and noRollbackFor lists exceptions not to be" 的内容,我会说。
更有趣的是,如果我在其 "throws" 子句中指定 IllegalArgumentException,上面的代码将停止回滚。是的,我不必这样做,因为它未经检查 - 但如果我这样做,noRollbackFor 似乎终于注意到它并且表现正常!有谁知道什么手册说这应该发生?或者这可能是一个错误?
UPDATE 这里是 spring 事务日志(在我的实际代码 YargReportTemplateDao$TemplateNotFoundException 中到处都是而不是 IllegalArgumentException)
1) 与 "throws"
[qtp22373939-44] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [ru.it.p321.dao.YargReportTemplateDaoImpl.getByCode] after exception: ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[pool-28-thread-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit
[qtp22373939-44] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Applying rules to determine whether transaction should rollback on ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[qtp22373939-44] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Winning rollback rule is: NoRollbackRuleAttribute with pattern [ru.it.p321.dao.YargReportTemplateDao$TemplateNotFoundException]
2) 没有“抛出
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [ru.it.p321.dao.YargReportTemplateDaoImpl.getByCode] after exception: org.springframework.dao.InvalidDataAccessApiUsageException: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION; nested exception is ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Applying rules to determine whether transaction should rollback on org.springframework.dao.InvalidDataAccessApiUsageException: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION; nested exception is ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Winning rollback rule is: null
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - No relevant rollback rule found: applying default rules
您看到的行为与事务处理无关,而是与异常转换有关。默认情况下,当 class 被注释为 @Repository
时,Spring 将注册一个 PersistenceExceptionTranslationInterceptor
,它将异常转换为 Spring DataAccessException
之一。默认情况下,它会翻译所有异常,除非抛出的异常在 throws 子句中声明。
这个异常转换发生在 TransactionInterceptor
之前,这样就不会抛出 IllegalArgumentException
,因为它已经被转换成其他东西了。
创建您赢得的自定义异常(从异常扩展)并应用 noRollBackFor 您的自定义异常 class
我见过很多类似的问题,但它们通常与我的问题无关。
这是我的代码。
@Override //class implements interface
//can also add "rollbackFor = OutOfMemoryError.class" here, to no avail
@Transactional(noRollbackFor = IllegalArgumentException.class)
public ReportTemplate getByCode(final String code)
//throws IllegalArgumentException - see question text
{
if(code == null) {
throw new IllegalArgumentException("ss");
}
}
消费者(非事务性)通过自动装配接口调用此方法。 尽管 noRollbackFor 事务(仅由此方法组成)被回滚。 好的,我理解那些说 "by default it's rollbackFor any unchecked, so since the default is not overridden, that rule still applies" 的人。但这不应该是真的,因为那意味着 noRollbackFor 是无用的:)我们可以尝试像上面的评论中那样指定 rollbackFor,希望它会取消 "default" rollbackFor - 但这无济于事:回滚仍然发生;看起来这个设置只是添加到 "default"。最糟糕的是,当 noRollbackFor 和 rollbackFor 覆盖相同的后代异常时,我找不到关于它应该如何工作的精确规范(比如在我的例子中,RuntimeException vs IllegalArgumentException,谁赢了?)。
好吧,我找到了 but one official clarification,上面写着 "the strongest matching rule wins" - 但这似乎不是普遍正确的,就像我的情况一样。此外,出于某种原因,它们过于具体:他们说 no-rollback-for="InstrumentNotFoundException" 意味着,从字面上看,"any exception other than an InstrumentNotFoundException" 将被回滚(但是 InstrumentNotFoundException 的后代呢?)而且无论如何它已经过时了: 2.5.x,而较新的文档只是以一种相当矛盾的方式说了类似 "rollbackFor lists exceptions to be rolled back, and noRollbackFor lists exceptions not to be" 的内容,我会说。
更有趣的是,如果我在其 "throws" 子句中指定 IllegalArgumentException,上面的代码将停止回滚。是的,我不必这样做,因为它未经检查 - 但如果我这样做,noRollbackFor 似乎终于注意到它并且表现正常!有谁知道什么手册说这应该发生?或者这可能是一个错误?
UPDATE 这里是 spring 事务日志(在我的实际代码 YargReportTemplateDao$TemplateNotFoundException 中到处都是而不是 IllegalArgumentException)
1) 与 "throws"
[qtp22373939-44] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [ru.it.p321.dao.YargReportTemplateDaoImpl.getByCode] after exception: ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[pool-28-thread-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit
[qtp22373939-44] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Applying rules to determine whether transaction should rollback on ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[qtp22373939-44] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Winning rollback rule is: NoRollbackRuleAttribute with pattern [ru.it.p321.dao.YargReportTemplateDao$TemplateNotFoundException]
2) 没有“抛出
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [ru.it.p321.dao.YargReportTemplateDaoImpl.getByCode] after exception: org.springframework.dao.InvalidDataAccessApiUsageException: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION; nested exception is ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Applying rules to determine whether transaction should rollback on org.springframework.dao.InvalidDataAccessApiUsageException: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION; nested exception is ru.it.p321.dao.YargReportTemplateDaoImpl: Yarg template was not found for given code: ITORG_REJECT_NOTIFICATION
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - Winning rollback rule is: null
[qtp21176461-48] TRACE org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - No relevant rollback rule found: applying default rules
您看到的行为与事务处理无关,而是与异常转换有关。默认情况下,当 class 被注释为 @Repository
时,Spring 将注册一个 PersistenceExceptionTranslationInterceptor
,它将异常转换为 Spring DataAccessException
之一。默认情况下,它会翻译所有异常,除非抛出的异常在 throws 子句中声明。
这个异常转换发生在 TransactionInterceptor
之前,这样就不会抛出 IllegalArgumentException
,因为它已经被转换成其他东西了。
创建您赢得的自定义异常(从异常扩展)并应用 noRollBackFor 您的自定义异常 class