这是一个简单的产品实体,指的是一个子组:
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);
我想我不知何故需要参考地图键,但不知道如何。
答案 0 :(得分:2)
这些是你在这里有点复杂的映射,我不确定是否有更简单的方法来实现这一点。希望有人能提供更好的答案,但作为替代方案,总有能力预先加载到持久化上下文中,您知道将使用n + 1选择获取的所有实体实例。
因此,在触发查询之前,只需加载预期要获取的所有ProductSubGroup
:
select p.productSubGroup from Product p
where p in (select index(byproducts) from FinishedProduct)
当然,请对原始查询中的子查询中的FinishedProduct
重复任何其他限制,以避免加载您不需要的ProductSubGroup
。
作为更好的替代方案(在我看来),您可能需要考虑为Product.productSubGroup
关联定义@BatchSize
。那样ProductSubGroup
将分批加载,而不是一个一个地加载。