gpt4 book ai didi

java - 服务器抛出 OptimisticLockException 后事务没有完全回滚

转载 作者:行者123 更新时间:2023-11-29 08:47:15 26 4
gpt4 key购买 nike

假设我有一个带有版本字段(javax.persistence.Version 注释)的实体 bean AccountBean。在交易过程中,我的应用程序修改了这个实体并对其他实体执行数据库操作(插入和更新行)。其中一些实体 bean 具有 @Version 字段,但不是全部。

当同一个 AccountBean 实体被 2 个线程同时修改时,OptimistickLockException 被抛出并且(至少根据服务器日志)事务被回滚。但是,只有对冲突的 AccountBean 实体所做的更改才会实际回滚 - 其他所有内容都提交给数据库。

**编辑:**我添加了简单的源代码来说明问题;该应用程序是一个 REST Web 服务;两个测试线程使用相同的帐户 ID 并发调用操作“更新”。再次抛出 OLE,但据称回滚的事务提交给数据库新的 AccountHistory 实体:/由于事务是由容器管理的,因此事务在调用方法更新时启动,并在返回值时提交;这也是抛出 OLE 的时候。

//UpdateAccount.java
@Stateless
@Path("account")
public class UpdateAccount {

@PersistenceContext
EntityManager em;

@Path("update")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String update(Long accountId) {
Account account = em.find(Account.class, accountId);
if(null == account) {
return "account not found";
} else {
return executeUpdate(account);
}
}

String executeUpdate(Account account) {
Integer newValue = account.getValue() + 1;

em.persist(getAccountHistory(account, newValue));
account.setValue(newValue);

return "ok";
}

AccountHistory getAccountHistory(Account account, Integer newValue) {
AccountHistory history = new AccountHistory();
history.setId(new Date().getTime());
history.setAccount(account);
history.setValueBefore(account.getValue());
history.setValueAfter(newValue);

return history;
}
}

//Account.java
@Entity
public class Account {

@Id
private Long id;

@Column
private Integer value;

@Version
private Long version;

(...)//getters, setters etc
}

//AccountHistory.java
@Entity
public class AccountHistory {

@Id
private Long id;

@Column
private Integer valueBefore;

@Column
private Integer valueAfter;

@ManyToOne
@JoinColumn(name = "idaccount")
private Account account;

(...)//getters, setters etc
}
  1. 我期望所有更改都回滚是错误的吗?
  2. 我可以手动强制完全回滚吗?我尝试手动管理交易,捕获 OLE 并调用回滚(如 Adam Bien'sblog 中所述)。但是,当我发现异常时,交易是已标记为回滚。

我使用 JRE 1.7 在 jboss-eap-6.1/jboss-as-7.1.1Final 上部署我的应用程序,并使用 Hibernate(这些服务器的默认版本)。我的 persistence.xml 文件非常简单。我没有设置任何额外的属性。

最佳答案

当事务回滚时,该事务中所做的所有更改也将被回滚。

对于本地事务,这是由 JDBC 连接处理的,对于全局事务,则通过回滚所有登记的 JDBC 事务来处理。

因此,Hibernate 不控制回滚或不回滚的内容。底层的事务管理器起到了作用。

只有当您的服务代码使用多个事务(例如嵌套事务、REQUIRES_NEW)或从一个非事务服务调用两个连续的事务服务时,才会提交一些更改并回滚一些更改。因此,如果第二个回滚,第一个无论如何都会被提交,因为第一个服务不是事务性的,因此任何后续的服务调用都会在它自己的事务中登记。

关于java - 服务器抛出 OptimisticLockException 后事务没有完全回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24491029/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com