如果可以的话,我有几个关于 Spring 事务的问题。
假设我有这个 DAO 类:
public class MyDAO {
/**
* verifies if a certain record in DB contains 'True' in a certain Column named publishFlag
*/
@Transactional
public bloolean isBeingPublished(Long recordID){
...
}
/**
* sets the record's publishFlag column to true indicating that it's being published
*/
@Transactional
public boolean setBeingPublished(Long recordID){
...
}
}
下面的类使用它:
public class MyClass {
@Autowired
MyDAO dao;
public void publishRecords(List<Long> ids){
for(Long id : ids){
if(!dao.isBeingPublished(id)){
dao.setBeingPublished(id);
//do something to publish the record
}
}
}
}
我的问题是:
首先,将!dao.isBeingPublished(id)
and dao.setBeingPublished(id)
在同一个事务中执行还是在单独的事务中执行?
第二个问题是关于并发,多个MyClass
可以创建实例并并发调用publishRecord
方法可能会发生,因此两个并发调用!dao.isBeingPublished(id)
可能都会给出相同的结果,从而创造记录发表两次!我会考虑制作publishRecords
同步,但应用程序可能部署在多个服务器上,这使得同步声明毫无用处,因此我对事务有疑问,因为数据库是部署在这些服务器上的应用程序之间的唯一共享资源。
我的问题的具体解决方案是什么?我读到了 spring 的事务传播并发现REQUIRES_NEW
即使当前正在执行交易,也会创建一个新交易,但我仍然看不出这将如何解决我的问题。
预先感谢您的帮助。
需要考虑的事情很少,DAO专注于对单个实体的操作,而服务专注于对一个或多个实体的操作,因此事务应该放在服务层,这样你就可以重用DAO的操作而不需要任何事务,而是让服务来决定交易何时开始和结束
- 它不是单个事务,而是两个单独的事务。
- 这是您当前设计的并发问题,请参阅以下建议。
界面
public interface MyClass {
public void publishRecords(List<Long> ids);
}
执行
@Service
@Transactional(readOnly = false)
class DefaultMyClass implements MyClass {
@Autowired
MyDAO dao;
// single transaction
@Override
public void publishRecords(List<Long> ids) {
for(Long id : ids){
if(!dao.isBeingPublished(id)){
dao.setBeingPublished(id);
//do something to publish the record
}
}
}
}
DAO
class MyDAO {
public bloolean isBeingPublished(Long recordID){
// bigbang
}
public boolean setBeingPublished(Long recordID){
// bigbang
}
}
使用上述设计,这两个问题都得到了解决。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)