Dre*_*ter 57 spring transactions
我正在尝试使用命令模式来允许我的Web层在单个事务的上下文中使用Hibernate实体(从而避免延迟加载异常).但是,我现在对如何处理交易感到困惑.
我的命令调用使用@Transactional注释注释的服务层方法.这些服务层方法中的@Transactional(readOnly=true)一些是只读的- 例如- 并且一些是读/写的.
我的服务层公开了一个命令处理程序,它执行代表Web层传递给它的命令.
@Transactional
public Command handle( Command cmd ) throws CommandException
Run Code Online (Sandbox Code Playgroud)
我假设我正确地使命令处理程序的handle()方法成为事务性的.这就是混乱的来源.如果命令的实现调用多个服务层方法,命令处理程序无法知道命令中调用的操作是只读,读/写还是组合两个.
我不明白传播在这个例子中是如何工作的.如果我要创建该handle()方法readOnly=true,那么如果该命令随后调用带有注释的服务层方法会发生什么@Transactional(realOnly=false)?
我希望更好地理解这一点并欢迎您的评论......
安德鲁
can*_*iru 72
首先,由于Spring本身并不执行持久性,因此无法指定readOnly应该具有什么意义.这个属性只是对提供者的一个提示,行为依赖于,在这种情况下,Hibernate.
如果指定readOnly为true,则将FlushMode.NEVER在当前Hibernate会话中设置刷新模式,以防止会话提交事务.
此外,将在JDBC Connection上调用setReadOnly(true),这也是底层数据库的提示.如果你的数据库支持它(很可能它),FlushMode.NEVER它的效果基本相同,但它更强,因为你甚至无法手动刷新.
现在让我们看看事务传播是如何工作的.
如果你不明确设置readOnly到true,你会读/写事务.根据事务属性(例如REQUIRES_NEW),有时您的事务会在某个时刻暂停,新的事务将被启动并最终提交,之后将恢复第一个事务.
好的,我们快到了.让我们看看readOnly这个场景带来了什么.
如果读/写事务中的方法调用需要readOnly事务的方法,则应该暂停第一个,因为否则在第二个方法结束时会发生刷新/提交.
相反,如果从需要读/写的readOnly事务中调用方法,则第一个方法将被挂起,因为它不能被刷新/提交,第二个方法需要它.
在readOnly-to-readOnly和read/write-to-read/write情况下,外部事务不需要被挂起(除非你明确指定传播).
dan*_*ter 22
从readOnly = true调用readOnly = false不起作用,因为上一个事务继续.
在您的示例中,服务层上的handle()方法正在启动新的读写事务.如果handle方法依次调用带注释的只读服务方法,则只读将不起作用,因为它们将参与现有的读写事务.
如果这些方法必须是只读的,那么您可以使用Propagation.REQUIRES_NEW对它们进行注释,然后它们将启动一个新的只读事务,而不是参与现有的读写事务.
这是一个有效的例子,CircuitStateRepository是一个spring-data JPA存储库.
BeanS调用transactional =只读Bean1,它执行查找并调用transactional = read-write Bean2,它保存一个新对象.
31 09:39:44.199 [pool-1-thread-1] DEBUG osorm.jpa.JpaTransactionManager - 使用名称[nz.co.vodafone.wcim.business.Bean1.startSomething]创建新事务:PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ""
Bean 2参与其中.
31 09:39:44.230 [pool-1-thread-1] DEBUG osorm.jpa.JpaTransactionManager - 参与现有交易
没有任何东西致力于数据库.
现在更改Bean2 @Transactional注释以添加propagation=Propagation.REQUIRES_NEW
Bean1启动只读tx.
31 09:31:36.418 [pool-1-thread-1] DEBUG osorm.jpa.JpaTransactionManager - 创建名为[nz.co.vodafone.wcim.business.Bean1.startSomething]的新事务:PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ""
Bean2启动一个新的读写tx
31 09:31:36.449 [pool-1-thread-1] DEBUG osorm.jpa.JpaTransactionManager - 暂停当前事务,创建名为[nz.co.vodafone.wcim.business.Bean2.createSomething]的新事务
Bean2所做的更改现在已提交到数据库.
这是一个例子,用spring-data,hibernate和oracle测试过.
@Named
public class BeanS {
@Inject
Bean1 bean1;
@Scheduled(fixedRate = 20000)
public void runSomething() {
bean1.startSomething();
}
}
@Named
@Transactional(readOnly = true)
public class Bean1 {
Logger log = LoggerFactory.getLogger(Bean1.class);
@Inject
private CircuitStateRepository csr;
@Inject
private Bean2 bean2;
public void startSomething() {
Iterable<CircuitState> s = csr.findAll();
CircuitState c = s.iterator().next();
log.info("GOT CIRCUIT {}", c.getCircuitId());
bean2.createSomething(c.getCircuitId());
}
}
@Named
@Transactional(readOnly = false)
public class Bean2 {
@Inject
CircuitStateRepository csr;
public void createSomething(String circuitId) {
CircuitState c = new CircuitState(circuitId + "-New-" + new DateTime().toString("hhmmss"), new DateTime());
csr.save(c);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 11
默认情况下,事务传播是必需的,这意味着同一事务将从事务调用者传播到事务调用者.在这种情况下,只读状态也会传播.例如,如果只读事务将调用读写事务,则整个事务将是只读的.
你能否在View模式中使用Open Session来允许延迟加载?这样你的句柄方法根本不需要是事务性的.
小智 5
它似乎忽略了当前活动事务的设置,它只将设置应用于新事务:
org.springframework.transaction.PlatformTransactionManager
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException
Return a currently active transaction or create a new one, according to the specified propagation behavior.
Note that parameters like isolation level or timeout will only be applied to new transactions, and thus be ignored when participating in active ones.
Furthermore, not all transaction definition settings will be supported by every transaction manager: A proper transaction manager implementation should throw an exception when unsupported settings are encountered.
An exception to the above rule is the read-only flag, which should be ignored if no explicit read-only mode is supported. Essentially, the read-only flag is just a hint for potential optimization.
| 归档时间: |
|
| 查看次数: |
112537 次 |
| 最近记录: |