我试图理解为什么下面的代码片段无法按预期工作。
我已经有customer
和id=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));