具有线程池的Spring JPA事务

时间:2018-10-20 09:30:02

标签: java spring spring-data-jpa spring-transactions

我试图理解为什么下面的代码片段无法按预期工作。

我已经有customerid=1234 and name=A1了。我正在创建2个可调用任务,并要求它们执行transnational update方法。

这两个事务同时运行(因为我从代码中读取了从数据库中读取客户副本后引入了1秒的延迟),并使用id=1234 and name=A1读取了原始客户

一个尝试update name from A1->A2,另一个尝试update name from A1->A3

我原本希望至少有1个事务会引发提交冲突/陈旧数据异常,但在以下情况下,两者都会成功。

您能帮助我很好地理解吗?我在概念上缺少什么吗?

Main.java

    @Autowired
    CustomerService service;

    // Update address from A1 to A2
    Callable<String> t1 = new Callable<String>() {

        @Override
        public String call() throws Exception {
            service.updateCustomer("1234", "A2");
            return "T1 Done";
        }
    };

    // Update address from A1 to A3
    Callable<String> t2 = new Callable<String>() {

        @Override
        public String call() throws Exception {
            service.updateCustomer("1234", "A3");
            return "T2 Done";
        }
    };

    ExecutorService executorService = Executors.newFixedThreadPool(2);
    executorService.invokeAll((Collection) Arrays.asList(t1, t2));

CustomerService.java

@Transactional
public void updateCustomer(String customerId, String customerName) {
    try {
        Optional<Customer> currentCopyHandle = repo.findById(customerId);
        Customer currentCopy = currentCopyHandle.get();

        Thread.sleep(1000);

        ObjectMapper mapper = new ObjectMapper();

        String customerDetails = currentCopy.getDetails();

        ObjectNode writableDetails = (ObjectNode) mapper.readTree(customerDetails);
        writableDetails.put("name", customerName);

        currentCopy.setDetails(mapper.writeValueAsString(writableDetails));

        repo.save(currentCopy);

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

编辑1 Customer.java

这是与Oracle 12c兼容的POJO,其中名称为details的字段被标记为@Lob,而oracle12c表具有json约束

@Entity
public class Customer {

@Id
@javax.persistence.Id
private String cid;

@Lob
private String details;

public Customer() {
}

@PersistenceConstructor
public Customer(String cid, String details) {
    super();
    this.cid = cid;
    this.details = details;
}

public String getCid() {
    return cid;
}

public void setCid(String cid) {
    this.cid = cid;
}

public String getDetails() {
    return details;
}

public void setDetails(String details) {
    this.details = details;
}
}

在开始本练习之前,我已经完成了以下活动。

String json = "{ \"cid\" : \"1234\", \"name\" : \"A1\", \"address\" : \"India\"}";

service.saveCustomer1(new Customer("1234", json));

1 个答案:

答案 0 :(得分:0)

谢谢JBNizet

在这里通过在模型中添加@Version属性来使用乐观锁定解决了我的问题。