交易/ spring事务传播是否解决了这个并发问题? [英] Would transactions/spring Transaction propagation solve this concurrency issue?

查看:203
本文介绍了交易/ spring事务传播是否解决了这个并发问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果可能,我有关于Spring中的事务的几个问题。
让我们假设我有这个DAO类:

  public class MyDAO {

/ *
*验证DB中的某条记录是否包含名为publishFlag的特定列中的True
* /
@Transactional
public bloolean isBeingPublished(Long recordID){
...
}

/ **
*将记录的publishFlag列设置为true,表示正在发布
* /
@Transactional
public boolean setBeingPublished(Long recordID){
...
}

}

而下面的类使用它:

  public class MyClass {

@Autowired
MyDAO dao;

public void publishRecords(List< Long> ids){

(Long id:ids){
if(!dao.isBeingPublished
dao.setBeingPublished(id);
//做某事发布记录
}
}

}
}

我的问题是:




  • !dao.isBeingPublished(id) dao.setBeingPublished(id)在同一个事务中执行, ?


  • 第二个问题关于并发性,可以创建多个 MyClass 实例, c $ c> publishRecord 方法,因此对!dao.isBeingPublished(id)的两个并发调用可能都给出相同的结果,记录发布两次!
    我会考虑使 publishRecords 同步,但应用程序可能部署在多个服务器上,无用的,因此我的问题关于交易,因为数据库是部署在这些服务器上的应用程序之间的唯一共享资源。




什么将是我的问题的解决方案?我阅读关于spring的事务传播,发现 REQUIRES_NEW 会创建一个新的事务,即使一个正在执行,但仍然,我只是看不到这将是

解决方案

div>

很少需要考虑的事情,DAO是关注单个实体的操作,而服务是关注一个或多个实体的操作,所以事务应该放在服务层,这样你可以重用DAO的操作没有任何事务,但让服务决定何时开始和结束事务


  1. 不是在单个事务中,而是两个单独的事务。

  2. 这是当前设计的问题并发问题,请参阅以下建议。

strong>

  public interface MyClass {
public void publishRecords(List< Long> ids);
}

实施

  @Service 
@Transactional(readOnly = false)
class DefaultMyClass implements MyClass {

@Autowired
MyDAO dao;

//单个事务
@Override
public void publishRecords(List< Long> ids){
(Long id:ids){
if (!dao.isBeingPublished(id)){
dao.setBeingPublished(id);
//做某事发布记录
}
}
}
}

DAO

  class MyDAO {

public bloolean isBeingPublished(Long recordID){
// bigbang
}

public boolean setBeingPublished(Long recordID){
// bigbang
}
}

使用上述设计,两个问题都解决了。 >

I have a couple of questions about Transactions in Spring if you may. Let's suppose i have this DAO class :

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){
    ...
    }

}

And the following class using it :

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
            }
        }

    }
}

My questions are :

  • First of all, will the !dao.isBeingPublished(id) and dao.setBeingPublished(id) be executed in the same transaction or in separate ones?

  • Second question's about concurrency, Multiple MyClass instances can be created and concurrent calls to the publishRecord method can occur, so two concurrent calls to !dao.isBeingPublished(id) might both give the same result and thus making the record published twice! I would consider making the publishRecords synchronized but the application may be deployed on multiple servers which renders the synchronized declaration useless, hence my question about transactions since the database is the only shared resource between the apps deployed on those servers.

What would be the solution to my problem exactly? I read about spring's transaction propagation and found out that REQUIRES_NEW would create a new transaction even if one is currently being executed, but still, I just can't see how that's going to be a solution to my problem.

Thank you in advance for your help.

解决方案

Few things need consider, DAO is focus on operation on single entity, and service is focus on operation of one or more entities, so the transaction should put on service layer, so you can reuse DAO's operation without any transaction, but let service to decide when start and end transaction

  1. It is not in single transaction, but two separate transaction.
  2. That is the problem concurrency issue with your current design, see the following suggestion.

Interface

public interface MyClass {
    public void publishRecords(List<Long> ids);
}

Implementation

@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
    }
}

Using the above design, both problems are being resolved.

这篇关于交易/ spring事务传播是否解决了这个并发问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆