为什么选择更新仅适用于版本控制的实体?

时间:2019-02-08 23:32:58

标签: sql database spring transactions hsqldb

我在Spring data-jpa中使用HSQLDB 2.4.1。 我看到如果字段'@Version'不存在,则另一个线程能够更新同一行。 Spring'@Scheduled'运行的2个线程以特殊状态更新记录,意味着该状态尚未处理。

存储库中的读取方法:

@Lock(LockModeType.PESSIMISTIC_READ)
@Query("select t from Task t where t.state = 0")
Page<Task> findUnprocessed(Pageable p);

'process1'和'process2'执行几乎相同的简单更新,但是'process1'在保存之前有较长的暂停时间。

@Scheduled(fixedDelay = 10)
@Transactional(Transactional.TxType.REQUIRED)
public void process1() throws Exception {
    try {
        Task task = getTasks();
        System.out.println("process1: " + task + " by " + Thread.currentThread().getName());
        task.data= task.data + " by 1";
        task.state = 1;
        Thread.sleep(random.nextInt(4_000));
        repo.save(task);
        System.out.println("process1 updated: " + task.id);
        System.out.println("process1 read same = " + repo.findById(task.id));
    } catch (EmptyResultDataAccessException e) {
        //do nothing
    }
}

处理日志:

process1: Task(id=1) by thr-1
process2: Task(id=1) by thr-2
process2 updated: 1
process2 read same = Task(id=1, data= by 2) <<!!!
process2: Task(id=2, data=) by thr-2
process2 updated: 2
process2 read same = Task(id=2, data= by 2)
process1 updated: 1
process1 read same = Task(id=1, data= by 1) <<!!!

结果是,任务#1在由process2更新之后,由“ process1”更新。为什么使用“锁定更新”? 一切正常,使用“ @Version”字段(然后process2出现异常)。

1 个答案:

答案 0 :(得分:0)

您需要设置HSQLDB数据库的并发控制模型。如果要进行悲观锁定,请使用SET DATABASE TRANSACTION CONTROL LOCKS。这将启用读取锁定和写入锁定。

有关详细信息,请参见指南http://hsqldb.org/doc/2.0/guide/sessions-chapt.html#snc_tx_tx_cc