Hibernate 提供了多种机制来应对并发更新导致的数据不一致问题,主要包括以下几种:

1. 乐观锁(Optimistic Locking)

原理:

  • 假设并发冲突极少发生,允许多个事务并发读写,只有在提交更新时检查数据版本。
  • Hibernate 通过一个 @Version 注解字段(如 version 或 timestamp)来实现版本控制。

示例:

@Version
private int version;

工作流程:

  • 每次更新前,Hibernate 会自动检查数据库中记录的 version 是否与当前对象匹配。
  • 若不匹配,说明有其他事务已修改数据,则抛出 OptimisticLockException

适用场景:

  • 读多写少、冲突概率低的应用场景。

2. 悲观锁(Pessimistic Locking)

原理:

  • 假设并发冲突频繁发生,每次读取数据时就加锁,阻止其他事务读或写。
  • Hibernate 提供 LockMode(如 PESSIMISTIC_WRITE)实现数据库级锁。

示例:

Session session = entityManager.unwrap(Session.class);
session.get(User.class, userId, LockMode.PESSIMISTIC_WRITE);

工作流程:

  • 查询数据时加锁,直到事务结束,其他事务只能等待或失败。

适用场景:

  • 冲突概率高、对数据一致性要求高的应用,如金融、库存系统。

3. 数据库事务隔离级别

Hibernate 依赖底层数据库的事务隔离机制(如 READ COMMITTED、REPEATABLE READ、SERIALIZABLE)来避免脏读、不可重复读和幻读。

  • 可以通过 Hibernate 配置设置事务隔离级别:
hibernate.connection.isolation = 4  # 对应 Connection.TRANSACTION_REPEATABLE_READ

4. 应用层重试机制

结合乐观锁机制,遇到版本冲突时可以捕获异常并自动重试:

int retries = 3;
while (retries-- > 0) {
    try {
        // 加载实体、修改、提交事务
        break;
    } catch (OptimisticLockException e) {
        // 重试逻辑
    }
}

小结

机制是否加锁优点缺点
乐观锁性能高,适合读多写少冲突时可能多次重试
悲观锁保证强一致性性能较差,容易产生死锁
事务隔离级别底层机制数据库直接控制并发可配置性有限,开销大