我想在某些用例中急切地获取一对多
List
-s(但并非总是如此,所以 @OneToMany(fetch=FetchType.EAGER)
不会很好),并且我还希望 JPA 使用单独的 SQL 选择来获取这些 List
-s(每个 List
一个选择,而不是每个 List
项一个选择),而不是 SQL 连接。那是因为笛卡尔积(我有两个独立的列表)。
您可能认为我可以使用 JPA 2.1 实体图(毕竟这就是它的用途,以临时方式将属性标记为 eager)或使用 JPQL(或标准 API)不太优雅
left join fetch
。但这些似乎坚持使用 SQL 连接(在 left join fetch
的情况下并不奇怪),即使它们最终得到 MultipleBagFetchException
,它们也不会回退到获取一些 List
-s在单独的 SQL 选择中。实际上,我的案例也是一个多袋案例,但在您将我重定向到使用 Set
-s 等进行处理之前,请注意,前提是我不想要连接(太大的笛卡尔积)。现在,只是为了逗我,如果我用 List
注释 @OneToMany(fetch=FetchType.EAGER)
属性,Hibernate 将足够聪明,在单独的选择中获取 List
-s 以避免多个包(而且我什至可以使用Hibernate 的 Fetch
注释)。因此,JPA 2.1 实体图似乎无法兑现 ad-hoc FetchType.EAGER
的承诺,因为它们的行为很像 ad-hoc 获取连接,而我们在它们之前也已经有了这种连接。还是我错过了什么?
我突然想到,我应该在初始查询后调用
parentEntity.getSomeList().size()
,这次不会尝试急切地获取列表,但问题是,我还需要急切地获取列表项本身的一些属性,并且我无法为上述调用指定实体图。我还可以自己创建一个 JPA 查询,它只能通过所述急切的获取获取“someList”(这些没有问题),但是如何将结果列表放回到 parentEntity
中?如果我调用 parentEntity.setSomeList(fetchedList)
,parentEntity
就会变脏(尽管它不在关联的所有者一侧),因此它将是 SQL update-d(只是为了破坏最后修改时间和乐观锁定版本)。
另一种方法是将同一个表映射到两个不同的实体中。因此,当您需要具有多个选择的 EAGER 行为时,您可以使用以下实体:
@Fetch(FetchMode.SELECT)
@ManyToOne(fetch = FetchType.EAGER)
当你想要懒惰时,你可以使用另一个实体:
@Fetch(FetchMode.SELECT)
@ManyToOne(fetch = FetchType.LAZY)
我使用了@Dherik的方法,没有任何问题。