Java JPA:在JPQL中使用构造函数表达式在DTO中包装单个实体时,绕过N+1

Java JPA:在JPQL中使用构造函数表达式在DTO中包装单个实体时,绕过N+1,java,hibernate,jpa,jpql,spatial,Java,Hibernate,Jpa,Jpql,Spatial,首先,我知道类似的问题,但我的情况不同,其他问题没有任何充分的答案 我注意到,当我使用Hibernate作为我的JPA提供程序执行JPQL查询,并尝试使用构造函数表达式将实体包装到DTO中时,Hibernate似乎只选择实体的ID,这将导致N+1查询以获取其余属性 Hibernate版本:5.4.21.Final 查询: 查询日志: 正如您所看到的,我正在尝试使用hibernate spatial进行地理点附近的实体类型的查询,但我认为这与问题无关。如何让hibernate选择整个实体,然后将其

首先,我知道类似的问题,但我的情况不同,其他问题没有任何充分的答案

我注意到,当我使用Hibernate作为我的JPA提供程序执行JPQL查询,并尝试使用构造函数表达式将实体包装到DTO中时,Hibernate似乎只选择实体的ID,这将导致N+1查询以获取其余属性

Hibernate版本:5.4.21.Final

查询:

查询日志:

正如您所看到的,我正在尝试使用hibernate spatial进行地理点附近的实体类型的查询,但我认为这与问题无关。如何让hibernate选择整个实体,然后将其包装到DTO中?我已经试过做一个fetch self-join,但是没有用

Java类:使用Lombok

@价值观 公共类距离结果{ 地点; 双测距仪; } @诺尔格构装师 @吸气剂 @塞特 @托斯特林 @实体 @Tablename=PLACES 公共类位置扩展BaseEntity{ 公共PlaceString名称、点位置{ this.name=名称; 这个位置=位置; } @身份证 @GeneratedValuestrategy=GenerationType.IDENTITY 私人长id; 私有字符串名称; 专用点位置; }
BaseEntity几乎可以从spring数据jpa sans ID定义中抽象持久化。

我找到了一个解决方案,但不确定这是否是最好的方法。我没有在JPQL中使用构造函数表达式,而是使用了特定于hibernate的ResultTransformer

代码:

公共列表查找距离点中心,双半径米{ 字符串jpql=选择p,距离:中心,p.位置距位置p,其中dwithin:center,p.location,:radiusMeters=true; 返回列表entityManager.createQueryjpql .setParametercenter,中心 .SetParameter地形仪、半径仪 .unwrapQuery.class .SETRESULT变压器 ListResultTransformer 元组、别名->新建距离结果 放置元组[0], 数字元组[1]。双值 .getResultList; } 注意:ListResultTransformer是Vlad Mihalcea的hibernate类型库的一部分。另见:

查询日志:


您的名称和位置字段没有@Column注释,对吗?这是因为这些字段的默认命名与我的db架构匹配。我尝试添加@Column,但它不会改变行为。我现在不会将自己的答案标记为已接受。希望有一些外部的投入。
select new com.example.DistanceResult(p, distance(:center, p.location)) from Place p where dwithin(:center, p.location, :radiusMeters) = true
select place1_.id as col_0_0_, st_distance(?, place0_.location) as col_1_0_ from places place0_ inner join places place1_ on (place0_.id=place1_.id) where st_dwithin(?, place0_.location, ?)=true
binding parameter [1] as [OTHER] - [POINT (10.90943 48.37102)]
binding parameter [2] as [OTHER] - [POINT (10.90943 48.37102)]
binding parameter [3] as [DOUBLE] - [2000.0]

select place0_.id as id1_0_0_, place0_.location as location2_0_0_, place0_.name as name3_0_0_ from places place0_ where place0_.id=?
binding parameter [1] as [BIGINT] - [3]

select place0_.id as id1_0_0_, place0_.location as location2_0_0_, place0_.name as name3_0_0_ from places place0_ where place0_.id=?
binding parameter [1] as [BIGINT] - [4]
select place0_.id as col_0_0_, st_distance(?, place0_.location) as col_1_0_, place0_.id as id1_0_, place0_.location as location2_0_, place0_.name as name3_0_ from places place0_ where st_dwithin(?, place0_.location, ?)=true
binding parameter [1] as [OTHER] - [POINT (10.90943 48.37102)]
binding parameter [2] as [OTHER] - [POINT (10.90943 48.37102)]
binding parameter [3] as [DOUBLE] - [2000.0]