如何获取 @ElementCollection 地图的相关表
How to fetch an @ElementCollection map's related tables
这是一个引用子组的简单产品实体:
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);
我想我不知何故需要参考地图键,但不知道如何。
这里的映射有点复杂,我不确定是否有更简单的方法来完成此操作。希望有人会提供更好的答案,但作为替代方案,始终能够将您知道将通过 n+1 选择获取的所有实体实例预加载到持久性上下文中。
因此,在触发您的查询之前,只需加载所有 ProductSubGroup
预计会被提取的内容:
select p.productSubGroup from Product p
where p in (select index(byproducts) from FinishedProduct)
当然,在原始查询中的子查询中重复对 FinishedProduct
的任何其他附加限制,以避免加载不需要的 ProductSubGroup
。
作为更好的选择(在我看来),您可能需要考虑为 Product.productSubGroup
关联定义 。这样 ProductSubGroup
将分批加载,而不是一个接一个地加载。
这是一个引用子组的简单产品实体:
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);
我想我不知何故需要参考地图键,但不知道如何。
这里的映射有点复杂,我不确定是否有更简单的方法来完成此操作。希望有人会提供更好的答案,但作为替代方案,始终能够将您知道将通过 n+1 选择获取的所有实体实例预加载到持久性上下文中。
因此,在触发您的查询之前,只需加载所有 ProductSubGroup
预计会被提取的内容:
select p.productSubGroup from Product p
where p in (select index(byproducts) from FinishedProduct)
当然,在原始查询中的子查询中重复对 FinishedProduct
的任何其他附加限制,以避免加载不需要的 ProductSubGroup
。
作为更好的选择(在我看来),您可能需要考虑为 Product.productSubGroup
关联定义 ProductSubGroup
将分批加载,而不是一个接一个地加载。