【发布时间】:2014-11-27 11:18:01
【问题描述】:
我想要求每个 JPA 调用都发生在 @Transactional 上下文中,如果我忘记了那个注释,JPA 应该抛出一个异常,而不是为每个调用创建隐式事务。我怎样才能做到这一点?
【问题讨论】:
标签: spring hibernate jpa transactions spring-transactions
我想要求每个 JPA 调用都发生在 @Transactional 上下文中,如果我忘记了那个注释,JPA 应该抛出一个异常,而不是为每个调用创建隐式事务。我怎样才能做到这一点?
【问题讨论】:
标签: spring hibernate jpa transactions spring-transactions
您的问题中有一部分更容易回答“JPA 应该抛出异常而不是为每个调用创建隐式事务”。你知道transaction propagation levels
MANDATORY
Support a current transaction, throw an exception if none exists.
NESTED
Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.
NEVER
Execute non-transactionally, throw an exception if a transaction exists.
NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists.
REQUIRED
Support a current transaction, create a new one if none exists.
REQUIRES_NEW
Create a new transaction, suspend the current transaction if one exists.
SUPPORTS
Support a current transaction, execute non-transactionally if none exists.
REQUIRED 是默认值,您搜索的语义符合 MANDATORY。这可以通过在类级别上使用 @Transactional(propagation = Propagation.MANDATORY) 轻松配置,对于您希望展示此行为的所有 bean(DAO 层 bean 是通常的嫌疑人,因为它们不应该是事务所有者,而是始终在更大的上下文)。
要回答的棘手部分是如何在您实际省略@Transactional 时强制执行它。省略注释并不能保证任何事情,可能是事务语义是通过AOP 添加的。或者该类根本不管理事务。
我绝对建议将 REQUIRED 保留为默认值,并通过始终使用适当的传播级别声明 @Transactional 来微调传播级别。
但是,要尝试回答省略位,您还可以在 spring 配置中全局更改默认传播级别,例如
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" propagation="MANDATORY"/>
</tx:attributes>
</tx:advice>
通过这样做,您将有效地掷硬币,并为您未使用 @Transactional(propagation = PROPAGATION.REQUIRED); 标记的所有方法获得例外
【讨论】: