【发布时间】:2021-07-11 07:12:16
【问题描述】:
我正在使用 Spring 数据 JPA,并且我有一个使用 Spring 的 @Transactional 注释进行注释的方法。在该方法中,我从数据库中获取实体。一些实体用于只读目的,而一些实体在该事务中更新。举个例子吧
@Transactional
public void method1(Long id) {
var entityA = repositoryA.findById(id);
var entityB = repositoryB.findByOtherId(id);
entityA.setProperty1(entityB.getProperty() + 1);
}
@Transactional
public void method2(Long id) {
var entityA = repositoryA.findById(id);
var entityB = repositoryB.findByOtherId(id);
entityA.setProperty2(entityB.getProperty() + 2);
}
在上面的例子中,假设entityA和entityB分别对应tableA和tableB,property1和property2是tableA的两列。
另外,我使用的是 SQL Server,所以默认隔离级别是READ_COMMITTED。
我有以下问题:
-
执行
var entityA = repositoryA.findById(id);行后,如何确定应该获取哪种类型的锁?上例中,我们更新tableA中的数据,读取tableB中的数据,那么这里获取的锁是不同的吗? -
假设
method1和method2使用相同的id同时调用。首先获得锁的线程会阻塞第二个线程还是并行执行?我知道隔离级别是READ_COMMITTED,但数据库不知道我是否对第一个线程获取的行进行了任何更改。 -
如果我想为同一个
id并行执行这两种方法,应该设置什么隔离级别?同样在这两种方法中,我都在更新同一行的不同列,所以当两个事务提交时,它与串行执行这些事务的结果是否相同?附带说明一下,当 Hibernate 在提交阶段刷新更改时,对于更新语句,它会更新实体的所有字段,那么在这种情况下是否会丢失更新? -
如果我在Transactional注解中指定
readOnly=true,对获取锁有影响吗?
【问题讨论】:
-
"@Transactional" 本身在任何隔离级别上都不会启用任何锁定。要实现锁定行为,您应该在查询中使用“@Lock”注释或使用“for update”。在这里详细解释:stackoverflow.com/questions/58786195/…
-
"@Transactional" as itself on any isolation level doesn't enabling any locking这似乎与docs.microsoft.com/en-us/sql/t-sql/statements/…相矛盾 -
是的,你是正确的,我应该更准确。根据隔离级别,可以获取 READ 锁或共享锁,但如果没有其他操作,则不会创建 WRITE 锁或排他锁。
标签: java multithreading hibernate spring-data-jpa