MxN关系中有3个实体,B是关联实体。我们在单个TX中创建它们,保留所有它们,并通过OneToMany关联获取实体。提取后未初始化此关联。
来源:https://github.com/alfonz19/springboot222demo/commits/what
@Transactional
@Test
void contextLoads() {
// for(int i = 0; i < 3; i++) {
UUID aId = UUID.randomUUID();
AEntity aEntity = aRepository.save(new AEntity().setId(aId));
UUID bId = UUID.randomUUID();
CEntity cEntity = cRepository.save(new CEntity().setId(bId));
em.flush();
bRepository.save(new BEntity().setAEntity(aEntity).setCEntity(cEntity));
// }
em.flush();
// em.clear();
Iterable<CEntity> centities = cRepository.findAll();
List<BEntity> bEntities =
iterableToStream(centities).flatMap(e -> e.getBEntities().stream()).collect(Collectors.toList());
Assert.assertThat(centities, Matchers.iterableWithSize(1));
Assert.assertThat(bRepository.findAll(), Matchers.iterableWithSize(1));
Assert.assertThat(bEntities.size(), CoreMatchers.is(1));
...
}
好的,我知道,在创建BEntity
时,我不会更新AEntity
和CEntity
从而使它们损坏。调用cRepository.findAll()
然后在db上调用select来获取所有C(即使没有任何逐出/清除/清除),但@OneToMany尚未初始化。我不明白我会理解,如果根本就没有对db的调用,但是如果我还是要获取Cs来刷新它,为什么不还要刷新关联表。为什么那样?
更令人惊讶的是,编辑:好的,这一点也不奇怪,这意味着级联合并。完全可以。aRepository.save(new AEntity().setId(aId))
在执行em.merge(实体已分配ID)时,即使@OneToMany是惰性的,休眠也使用2个左外部联接来加载整个MxN结构。为什么那样?
我对此行为感到有点惊讶,因为在不应该出现的位置(IIUC)发出了选择,而在容易出现的位置没有发出选择。 >
并保持最佳状态。进行很小的更改:无需评论循环和清除,我将获得完整的不确定性行为。
来源:https://github.com/alfonz19/springboot222demo/tree/nondeterministic
测试将起作用,或产生如下异常:
但是,如果我在bEntities
变量声明上设置断点,则cEntities
总是正确创建的,然后进行测试。我不知道是什么原因造成的。
答案 0 :(得分:0)
我对非确定性行为问题的奖金问题有解答。
该列表的另一个随机生成的异常是org.springframework.orm.jpa.JpaSystemException: Found shared references to a collection
,并且所有这些行为都随着删除flatMap
而消失。即替换:
List<BEntity> bEntities =
StreamSupport.stream(centities.spliterator(), true).flatMap(e -> e.getBEntities().stream()).collect(Collectors.toList());
与
List<BEntity> bEntities = new LinkedList<>();
centities.forEach(e->bEntities.addAll(e.getBEntities()));
并在(不再是)“不确定”分支中进行测试将通过100%。不知道为什么,但是似乎hibernate管理的集合中的stream-api不那么安全。