我编写的代码存在 N+1 问题。 它是双向多对多关系。 我正在尝试使用 LEFT JOIN FETCH 解决它
我遇到的问题是,当我查看结果时,只有右侧的 1 个记录被加入。每个留下的记录应该还有更多。
左侧记录返回正确,但 Set 属性仅包含右侧的 1 个实例。
value = "SELECT cat from CatEntity cat "
+ "INNER JOIN cat.owner o "
+ "LEFT JOIN FETCH cat.toys "
+ "WHERE (o.name = :something)
我得到了全部 69 只猫的记录,但是有玩具的猫只有 1 个玩具。 如果我删除 LEFT JOIN FETCH。我得到了所有的猫和所有完整的玩具......当然还有 N+1 问题。 当我添加 LEFT JOIN FETCH.. 它解决了 N+1 问题,但不返回完整的玩具套装。
public class CatEntity implements Serializable {
@JoinTable(
name = "cat_toy",
joinColumns = {@JoinColumn(name = "cat_id")},
inverseJoinColumns = {@JoinColumn(name = "toy_id")})
@Fetch(FetchMode.JOIN)
@OrderBy(value = "toy_index desc")
private Set<ToyEntity> toys;
}
}
public class ToyEntity implements Serializable {
@ManyToMany(mappedBy = "toys")
Set<CatEntity> cats;
}
如何避免 N+1 问题但完全填充集合?
//公司不赞成发布代码,因此我使用 cat/toy 作为替换类名的示例。
最佳答案
我找到了解决问题的方法。我会在这里发帖希望对其他人有帮助。
我正在使用
@Fetch(FetchMode.JOIN)
在我的代码中。我需要使用
@Fetch(FetchMode.SUBSELECT)
这是专为 Collection 而设计的。它使用 2 个查询而不是 N+1 来填充 ManyToMany 双向关系的右侧。
它首先得到所有的猫。然后它得到所有的玩具。仅执行 2 个查询。
您不应将 LEFT JOIN FETCH 放入查询本身中。只需将获取模式添加到实体映射即可。
希望这对其他人有帮助。
关于java - ManyToMany N+1 问题 - 所有右侧均未返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70567098/