使用 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!

Stacktrace as gist

那就是 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