当前项目在Spring + Openjpa + Roo上运行。我有这样的实体
public class Zoo{
....
@OneToMany(mappedBy="zoo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Elephant> elephants;
@OneToMany(mappedBy="zoo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Jaguar> jaguars;
@OneToMany(mappedBy="zoo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Tiger> tigers;
....
}
然后我有一个简单的UI页面只是尝试更新Zoo名称,但是在简单查询之后从SQL跟踪日志
SELECT t0.id, t0.name
FROM Zoo t0
WHERE t0.id = ?
有这样的查询
SELECT * FROM Zoo, Tiger, TigerProduct, TigerFood, FoodSupplier, SupplierContacts...
和这样的数百个查询:
SELECT * FROM TigerProduct where tiger.id =: id_1
.....
SELECT * FROM TigerProduct where tiger.id =: id_n
....
....
SELECT * FROM TigerFood where tiger.id =: id_1
....
SELECT * FROM TigerFood where tiger.id =: id_n
同样对于美洲虎和大象也是如此。当数据库中存在大量数据时,这使得这个简单的操作非常慢。
第一个查询的java代码和后面的查询非常简单:
public static Zoo findZoo(Long id) {
if (id == null) return null;
return entityManager().find(Zoo.class, id);
}
从上面看起来,FetchType.Lazy
关系上的默认@OneToMany
看起来并不是很懒,以至于JPA试图拉动链上的所有数据。
那是怎么回事以及如何清除这种情况?我只喜欢有第一个查询,就是它
答案 0 :(得分:1)
FetchType.Lazy
只是一个提示,而不是一个要求。所以你不能依赖这种行为,你只能希望你的JPA提供者尊重你的提示。此外,JPA并没有强制将JPQL查询或实体管理器调用转换为SQL代码的方式,因此我们有责任选择一个知道如何做得更好的JPA提供者+版本(因为我们定义了更好的方法)。这可能是一个应该鼓励JPA提供者之间竞争的决定。