这是引用子组的简单产品实体:

public class Product implements Comparable<Product> {
    ...
    @ManyToOne(optional=false, fetch=FetchType.LAZY)
    @NotNull
    private ProductSubGroup productSubGroup;
    ...
}

我有一个在另一个实体中包含Product的地图:
public class FinishedProduct {
    ...
    @NotNull
    @ManyToOne
    private Product product;

    @ElementCollection(fetch=FetchType.LAZY)
    @MapKeyJoinColumn
    @Column(name="amount")
    @Sort(type=SortType.NATURAL)
    @Fetch(FetchMode.SUBSELECT)
    private SortedMap<Product, Double> byproducts = new TreeMap<>();
    ...
}

我可以使用以下代码加载地图:
Root<FinishedProduct> root = q.from(FinishedProduct.class);
root.fetch("product", JoinType.LEFT);
root.fetch("byproducts", JoinType.LEFT);

这可行,但是我需要存储在地图中的副产品的productSubGroup而不生成n + 1个选择。我该如何获取它们?仅将获取操作添加到最后会导致异常:
root.fetch("byproducts", JoinType.LEFT).fetch("productSubGroup", JoinType.LEFT);

org.springframework.dao.InvalidDataAccessApiUsageException:
Collection of values [null] cannot be source of a fetch

还尝试愚弄MapJoin,同样的例外:
MapJoin<FinishedProduct,Product,Double> map = root.joinMap("byproducts", JoinType.LEFT);
map.fetch("productSubGroup", JoinType.LEFT);

我想我需要以某种方式引用map键,但是不知道如何。

最佳答案

您在这里有一些复杂的映射,我不确定是否有更简单的方法可以完成此操作。希望有人会提供更好的答案,但是作为替代,总有能力将您知道的所有实体实例预加载到持久性上下文中,而这些实例将通过n + 1个选择来获取。

因此,在触发查询之前,只需加载所有期望获取的ProductSubGroup:

select p.productSubGroup from Product p
where p in (select index(byproducts) from FinishedProduct)

当然,在原始查询中对子查询重复其他对FinishedProduct的其他限制,以避免加载不需要的ProductSubGroup

作为更好的选择(我认为),您可能需要考虑为@BatchSize关联定义 Product.productSubGroup 。这样,ProductSubGroup将会批量加载,而不是一个一个地加载。

10-05 21:41