悲观锁

对于单一实体实例,当有极大的可能会出现并行编辑时,我们可以使用悲观锁机制。因为在这种情况下,基于实体版本的 乐观锁 机制会经常发生编辑冲突。

当实体实例在 UI 的详情视图打开时,悲观锁会显式锁定该实例。于是,在特定的时间段内,只有一个用户可以编辑这个实例。

Jmix 悲观锁机制还可以用来管理并行执行的任意流程。锁是分布式的,会在集群中进行复制。

安装

通过 Jmix 组件市场安装请按照 扩展组件 章节的说明进行。

手动安装,需在 build.gradle 文件添加下列依赖:

implementation 'io.jmix.pessimisticlock:jmix-pessimisticlock-starter'
implementation 'io.jmix.pessimisticlock:jmix-pessimisticlock-flowui-starter'

用法

如需启用某个实体的悲观锁,可以在实体类添加 @PessimisticLock 注解。示例:

@PessimisticLock(timeoutSec = 120)
@JmixEntity
@Table(name = "DOCUMENT")
@Entity
public class Document {
// ...

如果实体已经被其他人锁定,则通过标准实体详情视图打开实体时,会切换到只读模式,以此来处理悲观锁。

还可以使用 LockManager bean 在代码中锁定实体。例如:

@Autowired
private LockManager lockManager;

public void lockAndProcessDocument(Document document) {
    LockInfo lockInfo = lockManager.lock(document);
    if (lockInfo != null) {
        throw new IllegalStateException("Document is already locked by " +
                lockInfo.getUsername());
    }
    try {
        processDocument(document);
    } finally {
        lockManager.unlock(document);
    }
}

参阅 LockManager 接口的 Javadocs 了解更多。

锁过期

注解的 timeoutSec 属性用于配置锁的超时时限,单位为秒。默认值为 300 秒。

锁的自动过期机制依赖 Quartz 定时任务。需要在项目中包含 Quartz 扩展组件。

下列应用程序属性可以控制锁过期机制:

  • 设置 jmix.pslock.use-default-quartz-configurationfalse 可以禁用默认的过期机制。该属性默认为 true

  • 使用 jmix.pslock.expiration-cron 属性设置过期计划的 Cron 表达式。默认为 0 * * * * ? - 每分钟。

管理员 UI

锁的当前状态可以通过 Pessimistic Locking → Locks 视图查看。视图中可以对任意对象进行解锁。