使用 Spring 数据投影过滤
Filtering with Spring Data Projection
我已经为我的 Spring 数据存储库创建了一个基于 class 的投影。效果很好。然后我尝试用QueryDSL中的@QueryProjection注释构造函数,希望得到一个带有分页、排序和过滤的REST端点。
代码如下所示,但为简洁起见省略了更多字段和详细信息:
实体:
@Data
@Entity
public class Entity extends BaseEntity {
private String fieldA, fieldB;
private AnotherEntity ae;
}
DTO:
@Getter
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class EntityDto {
private final String fieldA;
private final String anotherEntityFieldC;
@QueryProjection
public EntityDto(final String fieldA, final String anotherEntityFieldC) {
this.fieldA = fieldA;
this.anotherEntityFieldC = anotherEntityFieldC;
}
}
存储库:
public EntityRepo extends JpaRepository<Entity, Long>, QuerydslBinderCustomizer<EntityPath<Entity>>, QuerydslPredicateExecutor<Entity> {
Page<EntityDto> findPageProjectedBy(Predicate predicate, Pageable pageable);
}
端点:
@RestController
@RequestMapping(EntityEndpoint.ROOT)
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public EntityEndpoint {
private final EntityRepo er;
@GetMapping
public ResponseEntity<PagedResources<Resource<EntityDto>>> getAllEntities(
Pageable pageable,
@QuerydslPredicate(root = EntityDto@.class) Predicate predicate,
PagedResourcesAssembler<EntityDto> assembler) {
Page<EntityDto> page = er.findPageProjectedBy(predicate, pageable);
return new ResponseEntity<>(assembler.toResource(page), HttpStatus.OK);
}
}
我得到异常:
java.lang.IllegalStateException: Did not find a static field of the same type in class at.dataphone.logis4.model.dto.QBuchungDto!
那就是 URL:
curl -X GET --header 'Accept: application/json' 'http://localhost:8080/Entity'
嗯,看来只能用实际实体查询了。
我认为它是 'WHERE'-clause 中的部分,它只能在所选实体中实际包含列,而 DTO 投影发生在 'SELECT'-clause 中。
@QueryProjection
-Annotation 似乎只服务于 QueryDsl 代码生成器来标记 class 然后可以用来 create projections in a select-clause
我已经为我的 Spring 数据存储库创建了一个基于 class 的投影。效果很好。然后我尝试用QueryDSL中的@QueryProjection注释构造函数,希望得到一个带有分页、排序和过滤的REST端点。
代码如下所示,但为简洁起见省略了更多字段和详细信息:
实体:
@Data
@Entity
public class Entity extends BaseEntity {
private String fieldA, fieldB;
private AnotherEntity ae;
}
DTO:
@Getter
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class EntityDto {
private final String fieldA;
private final String anotherEntityFieldC;
@QueryProjection
public EntityDto(final String fieldA, final String anotherEntityFieldC) {
this.fieldA = fieldA;
this.anotherEntityFieldC = anotherEntityFieldC;
}
}
存储库:
public EntityRepo extends JpaRepository<Entity, Long>, QuerydslBinderCustomizer<EntityPath<Entity>>, QuerydslPredicateExecutor<Entity> {
Page<EntityDto> findPageProjectedBy(Predicate predicate, Pageable pageable);
}
端点:
@RestController
@RequestMapping(EntityEndpoint.ROOT)
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public EntityEndpoint {
private final EntityRepo er;
@GetMapping
public ResponseEntity<PagedResources<Resource<EntityDto>>> getAllEntities(
Pageable pageable,
@QuerydslPredicate(root = EntityDto@.class) Predicate predicate,
PagedResourcesAssembler<EntityDto> assembler) {
Page<EntityDto> page = er.findPageProjectedBy(predicate, pageable);
return new ResponseEntity<>(assembler.toResource(page), HttpStatus.OK);
}
}
我得到异常:
java.lang.IllegalStateException: Did not find a static field of the same type in class at.dataphone.logis4.model.dto.QBuchungDto!
那就是 URL:
curl -X GET --header 'Accept: application/json' 'http://localhost:8080/Entity'
嗯,看来只能用实际实体查询了。
我认为它是 'WHERE'-clause 中的部分,它只能在所选实体中实际包含列,而 DTO 投影发生在 'SELECT'-clause 中。
@QueryProjection
-Annotation 似乎只服务于 QueryDsl 代码生成器来标记 class 然后可以用来 create projections in a select-clause