有什么办法可以使Hibernate中的悲观锁定和乐观锁定同时起作用

时间:2019-09-09 04:27:03

标签: hibernate optimistic-locking pessimistic-locking

我有一个这样的实体

@Entity
@Table(name = "ACC_ACCOUNT_INFO")
@Getter
@Setter
public class AccountInfoEntity implements Serializable {

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accountIdGenerator")
@SequenceGenerator(name = "accountIdGenerator", sequenceName = "SEQ_ACCOUNT")
@Id
@Column(name = "ID")
private long id;

@Column(name = "ACCOUNT_NO", nullable = false)
private String accountNo;

@Column(name = "ACCOUNT_TYPE", nullable = false)
@Enumerated(EnumType.STRING)
private AccountType accountType;

@Column(name = "ACCOUNT_NAME", nullable = false)
private String accountName;

@Column(name = "BANK_NAME", nullable = false)
private String bankName;

@Column(name = "EXPIRY_DATE", nullable = false)
private LocalDate expiryDate;

@Column(name = "STATUS", nullable = false)
private String accountStatus;

@Column(name = "PARENT_ACC_ID")
private Long parentAccountId;

@Column(name = "BALANCE", nullable = false)
private BigDecimal balance;

@Version
@Access(javax.persistence.AccessType.PROPERTY)
@Column(name = "VERSION")
private int version;

}

在我的情况下,可以同时更新一个帐户余额。因此,如果同时有两个请求更新同一帐户余额,则其中一个请求成功,另一个请求获得了乐观锁。因此,然后我尝试使用PESSIMISTIC_WRITE锁定模式更新帐户。但是当并发请求到达时,乐观锁错误仍然存​​在。然后,我从实体中删除了VERSION属性(乐观锁定),然后所有并发请求针对同一帐户成功执行。

现在我的问题是,可以同时使用两种锁定机制吗?

更新: 对于具有PESSIMISTIC_WRITE锁定模式的同一个帐户的5个并发呼叫,休眠会生成这样的查询

Hibernate: select * from acc_account_info accountinf0_ where accountinf0_.account_no=?
Hibernate: select * from acc_account_info accountinf0_ where accountinf0_.account_no=?
Hibernate: select * from acc_account_info accountinf0_ where accountinf0_.account_no=?
Hibernate: select * from acc_account_info accountinf0_ where accountinf0_.account_no=?
Hibernate: select * from acc_account_info accountinf0_ where accountinf0_.account_no=?


Hibernate: select id from acc_account_info where id =? and version =? for update
Hibernate: select id from acc_account_info where id =? and version =? for update
Hibernate: select id from acc_account_info where id =? and version =? for update
Hibernate: select id from acc_account_info where id =? and version =? for update
Hibernate: select id from acc_account_info where id =? and version =? for update

但是,如果锁定模式为PESSIMISTIC_FORCE_INCREMENT,则休眠状态不会为查询更新集生成select。因此,悲观锁不适用于PESSIMISTIC_FORCE_INCREMENT模式。

这是我的代码

public AccountInfoEntity findByAccNoPessimistic(String accountNo) {
    Query query = em.createQuery("From AccountInfoEntity where accountNo=:accountNo");
    query.setParameter("accountNo", accountNo);
    query.setLockMode(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
    AccountInfoEntity result = (AccountInfoEntity) query.getSingleResult();
    em.refresh(result);
    return result;
}

1 个答案:

答案 0 :(得分:0)

当您使用methods: { ...mapActions(["resetPassword"]), reset() { this.resetPassword({ token: this.$route.params.token, email: this.email, password: this.password }) .then(response => { toast.fire({ type: "success", title: "Password reset successfully." }); this.$router.push({ name: "login" }); }) .catch(error => { swal.fire({ type: "error", text: error.response.data.message, showConfirmButton: false, timer: 3000 }); }); } } } 并行检索实体时,只有一个调用应该成功,而其他调用应该被阻止。因此,您遇到乐观的锁定错误很奇怪。

在任何情况下,建议使用LockModeType.PESSIMISTIC_WRITE + LockModeType.PESSIMISTIC_FORCE_INCREMENT两种方式都可以使用。 (也就是说,默认情况下会有乐观锁,如果明确要求,则为悲观锁。)