用于检索复杂实体的高效 JPQL 查询
Efficient JPQL query for retrieving complex entities
我是JPA/JPQL的菜鸟,所以如果这个问题crystal不清楚,请原谅。
我正在尝试寻找一个高效的 JQPL 查询来获取复杂对象的所有记录。
(即由多个 table 表示,具有多个一对多关系 - 请参见下面的简化示例):
class ComplexObject {
private Set< SubOject1> so1 ...
.....
@OneToMany(fetch = FetchType.LAZY)
public Set< SubOject1>...
}
class SubObject1 {
private Set< SubOject2> so2 ...
.....
@OneToMany(fetch = FetchType.LAZY)
public Set< SubOject2>...
}
我正在使用以下 JPQL 查询:
select distinct CO
from ComplexObject CO
left join fetch CO.so1 SO1
left join fetch SO1.so2
查询是 运行 在无状态会话上,为了获得数据库中当前数据的实际快照,它与实体管理器分离(因此使用左连接提取) .
不幸的是,我遇到了 2 个问题:
由于复杂对象包含多个 so1 实例,并且每个 so1 实例包含多个 so2 实例,因此 SQL 查询的基础转换会生成一个特定的 select 查询所有 table 的乘积的行连接 - 一个非常浪费的解决方案。有没有办法减少内部 select 查询的数量? (这似乎是可怕的 N+1 查询问题)。
JPQL 查询 returns 每个内部的 ComplexObject 实例 SQL 查询所有 table 连接的产物 - 这意味着对 ComplexObject 实例的多个引用.为什么 'select distinct' 查询会发生这种情况?
我使用的JPA框架是hibernate,DB是HyperSQL。
(1) 问题原来与使用 p6spy
日志框架有关,它打印出大型数据库 table 的所有结果。日志记录格式导致错误假设许多查询正在执行。
在尝试微调性能时,使用本机查询似乎没有比使用 JPQL 查询更好的性能。
使用本机查询还会产生对象类型的结果,这需要 post 处理。
您可以使用视图对象只接收您想要的列:
StringBuilder sb = new StringBuilder();
sb.append(" SELECT new ").append(ObjectVO.class.getName()).append("(co.someInfo1, co.someInfo2, so1.someInfo )");
sb.append(" FROM ComplexObject co ");
sb.append(" JOIN co.subOject1s so1 ");
sb.append(" LEFT JOIN so1.so2 so2 ");
sb.append(" WHERE so1.id = :idSo1 AND so2 = :someThing");
Query q = em.createQuery(sb.toString());
q.setParameter("idSo1", idSo1);
q.setParameter("someThing", someThing);
List<ObjectVO> listResult = q.getResultList();
对象VO class:
public class ObjectVO {
private String info1;
private Long info2;
private String info3;
public PedidoModel(String info1, Long info2, String info3){
this.info1 = info1;
this.info2 = info2;
this.info3 = info3;
}
}
我是JPA/JPQL的菜鸟,所以如果这个问题crystal不清楚,请原谅。
我正在尝试寻找一个高效的 JQPL 查询来获取复杂对象的所有记录。
(即由多个 table 表示,具有多个一对多关系 - 请参见下面的简化示例):
class ComplexObject {
private Set< SubOject1> so1 ...
.....
@OneToMany(fetch = FetchType.LAZY)
public Set< SubOject1>...
}
class SubObject1 {
private Set< SubOject2> so2 ...
.....
@OneToMany(fetch = FetchType.LAZY)
public Set< SubOject2>...
}
我正在使用以下 JPQL 查询:
select distinct CO
from ComplexObject CO
left join fetch CO.so1 SO1
left join fetch SO1.so2
查询是 运行 在无状态会话上,为了获得数据库中当前数据的实际快照,它与实体管理器分离(因此使用左连接提取) .
不幸的是,我遇到了 2 个问题:
由于复杂对象包含多个 so1 实例,并且每个 so1 实例包含多个 so2 实例,因此 SQL 查询的基础转换会生成一个特定的 select 查询所有 table 的乘积的行连接 - 一个非常浪费的解决方案。有没有办法减少内部 select 查询的数量? (这似乎是可怕的 N+1 查询问题)。
JPQL 查询 returns 每个内部的 ComplexObject 实例 SQL 查询所有 table 连接的产物 - 这意味着对 ComplexObject 实例的多个引用.为什么 'select distinct' 查询会发生这种情况?
我使用的JPA框架是hibernate,DB是HyperSQL。
(1) 问题原来与使用 p6spy
日志框架有关,它打印出大型数据库 table 的所有结果。日志记录格式导致错误假设许多查询正在执行。
在尝试微调性能时,使用本机查询似乎没有比使用 JPQL 查询更好的性能。 使用本机查询还会产生对象类型的结果,这需要 post 处理。
您可以使用视图对象只接收您想要的列:
StringBuilder sb = new StringBuilder();
sb.append(" SELECT new ").append(ObjectVO.class.getName()).append("(co.someInfo1, co.someInfo2, so1.someInfo )");
sb.append(" FROM ComplexObject co ");
sb.append(" JOIN co.subOject1s so1 ");
sb.append(" LEFT JOIN so1.so2 so2 ");
sb.append(" WHERE so1.id = :idSo1 AND so2 = :someThing");
Query q = em.createQuery(sb.toString());
q.setParameter("idSo1", idSo1);
q.setParameter("someThing", someThing);
List<ObjectVO> listResult = q.getResultList();
对象VO class:
public class ObjectVO {
private String info1;
private Long info2;
private String info3;
public PedidoModel(String info1, Long info2, String info3){
this.info1 = info1;
this.info2 = info2;
this.info3 = info3;
}
}