提问人:Ban 提问时间:11/11/2023 最后编辑:Ban 更新时间:11/11/2023 访问量:29
Spring Data Jpa 隔离级别不起作用吗?
Is the Spring Data Jpa isolation level not working?
问:
环境
- 春季启动 3.1.5
- MySQL的8.031
我的想法如下
- 启动隔离级别设置为 SERIALZABLE 的事务。
- 如果上述 SERIALZABLE 事务没有完成,但另一个事务开始,它将在 SERIALZABLE 事务完成后运行。
隔离代码
@Slf4j
@Service
@RequiredArgsConstructor
public class PersonService {
private final PersonRepository personRepository; // JpaRepository
private Long wait = 5000L;
@Transactional(isolation = Isolation.SERIALIZABLE)
public List<Person> findAllSERIALIZABLE() throws InterruptedException {
log.info("SERIALIZABLE ALL start");
List<Person> all = personRepository.findAll();
Person person = all.get(0);
person.setName(String.valueOf(System.currentTimeMillis()));
Person person1 = all.get(1);
person1.setName(String.valueOf(System.currentTimeMillis()));
Thread.sleep(wait);
log.info("SERIALIZABLE ALL end");
return personRepository.saveAllAndFlush(all);
}
public List<Person> find1And2() {
log.info("1,2 find start");
List<Person> allById = personRepository.findAllById(List.of(1L,2L));
log.info("1,2 find end");
return allById;
}
}
测试代码
@Test
@DisplayName("SERIALIZABLE find test")
public void serializableFindTest() throws InterruptedException, ExecutionException {
CompletableFuture<List<Person>> serializableAll = CompletableFuture.supplyAsync(() -> {
try {
return personService.findAllSERIALIZABLE();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
Thread.sleep(1000);
CompletableFuture<List<Person>> find1And2 = CompletableFuture.supplyAsync(() -> personService.find1And2());
List<Person> people = serializableAll.get();
List<Person> people1 = find1And2.get();
// then
Assertions.assertEquals(people1.get(0).getName(),people.get(0).getName());
}
我以为顺序会是
1.可序列化所有开始、结束
2. find1和2开始、结束
但结果是不同的。
2023-11-11T14:23:04.585+09:00 INFO 18864 --- [onPool-worker-1] com.tx.test.service.PersonService : SERIALIZABLE ALL start
2023-11-11T14:23:04.702+09:00 DEBUG 18864 --- [onPool-worker-1] org.hibernate.SQL :
select
p1_0.id,
p1_0.name
from
person p1_0
Hibernate:
select
p1_0.id,
p1_0.name
from
person p1_0
2023-11-11T14:23:05.581+09:00 INFO 18864 --- [onPool-worker-2] com.tx.test.service.PersonService : 1,2 find start
2023-11-11T14:23:05.605+09:00 DEBUG 18864 --- [onPool-worker-2] org.hibernate.SQL :
select
p1_0.id,
p1_0.name
from
person p1_0
where
p1_0.id in (?,?)
Hibernate:
select
p1_0.id,
p1_0.name
from
person p1_0
where
p1_0.id in (?,?)
2023-11-11T14:23:05.610+09:00 INFO 18864 --- [onPool-worker-2] com.tx.test.service.PersonService : 1,2 find end
2023-11-11T14:23:09.822+09:00 INFO 18864 --- [onPool-worker-1] com.tx.test.service.PersonService : SERIALIZABLE ALL end
2023-11-11T14:23:09.887+09:00 DEBUG 18864 --- [onPool-worker-1] org.hibernate.SQL :
update
person
set
name=?
where
id=?
Hibernate:
update
person
set
name=?
where
id=?
2023-11-11T14:23:09.891+09:00 DEBUG 18864 --- [onPool-worker-1] org.hibernate.SQL :
update
person
set
name=?
where
id=?
Hibernate:
update
person
set
name=?
where
id=?
org.opentest4j.AssertionFailedError:
我不确定是否我对隔离级别了解不够,或者我是否设置不正确。
答: 暂无答案
上一个:如何在MySQL中声明变量?
评论