当前位置: 首页 > 知识库问答 >
问题:

有什么方法可以让悲观锁和乐观锁在Hibernate中都工作

韩单弓
2023-03-14

我有一个这样的实体

@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;

}

在我的场景中,可以同时更新帐户余额。因此,如果两个请求同时来更新同一帐户余额,其中一个请求成功,另一个请求获得乐观锁定。因此,我尝试用PESSIMSTIC_WRITE锁定模式更新帐户。但当并发请求到达时,乐观锁错误仍然存在。然后我从实体中删除了VERSION属性(乐观锁定),然后对于同一个帐户,所有并发请求都会成功。

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

更新:对于PESSIMSTIC_WRITE锁定模式Hibernate的同一帐户的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

但如果锁定模式为PESSIMSTIC_FORCE_INCREMENT,则Hibernate不会生成更新查询集的选择。因此悲观锁无法在PESSIMSTIC_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个答案

荀裕
2023-03-14

当您并行检索具有LockModeType.PESSIMISTIC_WRITE的实体时,只有一个调用应该成功,其他调用应该被阻止。因此,奇怪的是,您面临乐观锁错误。

在任何情况下< code>LockModeType。悲观_强制_增量 @Version是推荐的方法,它让两种机制都就位。(即,默认情况下将有一个乐观锁,如果明确要求,则为悲观锁)。

 类似资料:
  • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁与悲观锁的具体区别: http://www.cnblogs.com/Bob-FD/p/3352216.html

  • 本文向大家介绍说一下乐观锁和悲观锁?相关面试题,主要包含被问及说一下乐观锁和悲观锁?时的应答技巧和注意事项,需要的朋友参考一下 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。 数据库的乐观锁需要自

  • 本文向大家介绍Java并发问题之乐观锁与悲观锁,包括了Java并发问题之乐观锁与悲观锁的使用技巧和注意事项,需要的朋友参考一下 首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再

  • 我试图理解Hibernate中的悲观锁定机制(通过MySQL DB)。 我尝试运行以下示例: 但它并没有给我一个错误,而是执行得很好。是不是我误解了什么概念。这种行为正常吗? 我能够完美地测试乐观锁定,那么对于悲观锁定,是对概念有一些误解,还是我的代码缺少了一些东西。

  • 本文向大家介绍请你介绍一下,数据库乐观锁和悲观锁相关面试题,主要包含被问及请你介绍一下,数据库乐观锁和悲观锁时的应答技巧和注意事项,需要的朋友参考一下 考察点:数据库   悲观锁 悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。悲观锁:假定会发生并发冲突,屏蔽一切可

  • 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,会产生冲突,解决方案有两种:乐观锁、悲观锁。 悲观锁在这里不讲,自行Google。 乐观锁假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性,不完整则更新失败。 乐观锁实现方式 使用整数表示数据版本号.更新时检查版本号是否一致,如果相等,则更新成功,且版本号+1.如果不等,则数据已经被修改过,更新失败。 使用时间戳来实现。 本质上也