如果从readOnly=true调用readOnly=false,则无法正常工作,因为上一个事务将继续。
在您的示例中,服务层的handle()方法正在启动新的读写事务。如果handle方法反过来调用带有readonly注解的服务方法,则readonly不会起作用,因为它们将参与现有的读写事务。
如果这些方法对于只读操作至关重要,则可以使用Propagation.REQUIRES_NEW注释它们,然后它们将开始一个新的只读事务,而不是参与现有的读写事务。
这是一个可行的示例,CircuitStateRepository是Spring Data JPA存储库。
BeanS调用一个transactional=read-only Bean1,它执行查找并调用transactional=read-write Bean2保存一个新对象。
31 09:39:44.199 [pool-1-thread-1] DEBUG o.s.orm.jpa.JpaTransactionManager - 使用名称[nz.co.vodafone.wcim.business.Bean1.startSomething] 创建新事务: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
Bean2参与其中。
31 09:39:44.230 [pool-1-thread-1] DEBUG o.s.orm.jpa.JpaTransactionManager - 参与现有事务
没有向数据库提交任何内容。
现在将Bean2的@Transactional注解更改为添加propagation=Propagation.REQUIRES_NEW
Bean1开始一个只读事务。
31 09:31:36.418 [pool-1-thread-1] DEBUG o.s.orm.jpa.JpaTransactionManager - 使用名称[nz.co.vodafone.wcim.business.Bean1.startSomething] 创建新事务: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
Bean2开始一个新的读写事务
31 09:31:36.449 [pool-1-thread-1] DEBUG o.s.orm.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);
}
}
handle()
可能调用写入方法,因此事务必须允许写入。这将是一个很好且正确的解决方案。如果您真的想要,可以通过Command的属性来编程启动TX并切换为readOnly,但我认为这不值得努力。 - Thomas W