spring boot和jpa存储库处理多线程

时间:2016-09-13 08:30:24

标签: java spring-boot locking spring-data-jpa

我正在研究spring boot和jpa存储库,在处理多线程时遇到了一个问题。

数据库中有500个OfferCode,默认情况下,allocatedFlag设置为null,模型为“ABC”,代码在所有500条记录中都是唯一的。我试图在这里实现的目标是调用register方法来使用OfferCode并将allocatedFlag设置为1。 我在这里遇到的问题是这一行

System.out.println(Thread.currentThread().getName()+" offer code "+offerCode.getCode()+" "+offerCode.getAllocatedFlag());

有时它会打印不同的线程名称但使用相同的代码并且allocatedFlag为null。由于我使用的是同步,我认为理想情况下不应该发生。 如果正确执行了findTop1ByAllocatedFlagIsNullAndModel,一旦返回OfferCode,allocateFlag将被设置为1,然后第二个线程进入它不应该获得与最后一个线程相同的代码。 但是现在我得到了 对于线程A,我得到了例如,

Thread-A 0000-0000-00001 null
Thread-A 0000-0000-00001 1

对于线程B,我得到了例如,

Thread-B 0000-0000-00001 null
Thread-B 0000-0000-00001 1

我认为应该

Thread-B 0000-0000-00002 null
Thread-B 0000-0000-00002 1

所以我不确定我是否正确使用了synchronized或者JpaRepository存在一些问题

我还发现如果我将OfferCodeRepository更改为以下,那么它正在工作。所以有人知道这里有什么问题吗?

@Repository
public interface OfferCodeRepository extends JpaRepository<OfferCode, Integer>{
    @Lock(LockModeType.PESSIMISTIC_READ)
    Optional<OfferCode> findTop1ByAllocatedFlagIsNullAndModel(String model);
}

我的代码

@Entity
public class OfferCode {

    @Id
    @GeneratedValue
    private int id;
    @Version
    private int version;    
    private String model;
    private String code;
    private String allocatedFlag;
}

@Repository
public interface OfferCodeRepository extends JpaRepository<OfferCode, Integer>{
    Optional<OfferCode> findTop1ByAllocatedFlagIsNullAndModel(String model);    
}

@Service
public class OfferCodeServiceImpl implements OfferCodeService {
    @Autowired
    private OfferCodeRepository offerCodeRepository;
    @Override
    public Optional<OfferCode> findTop1ByAllocatedFlagIsNullAndModel(String model) {
        return offerCodeRepository.findTop1ByAllocatedFlagIsNullAndModel(model);
    }
    @Override
    public OfferCode update(OfferCode code) {
        return offerCodeRepository.saveAndFlush(code);
    }
}

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private OfferCodeService offerCodeService;

    @Transactional
    public synchronized Product register(Product product) {
        if(product!=null){
            Optional<OfferCode> optional =  offerCodeService.findTop1ByAllocatedFlagIsNullAndModel(product.getModel());
            optional.ifPresent(offerCode->{
                System.out.println(Thread.currentThread().getName()+" offer code "+offerCode.getCode()+" "+offerCode.getAllocatedFlag());
                offerCode.setAllocatedFlag("1");
                offerCodeService.update(offerCode); 
                System.out.println(Thread.currentThread().getName()+" offer code "+offerCode.getCode()+" "+offerCode.getAllocatedFlag());
            });

        }
        return product;
    }
}

0 个答案:

没有答案