繁体   English   中英

带有可选@Param 的 Spring 数据查询方法

[英]Spring Data Query Method with Optional @Param

是否可以允许查询方法 @Params 是可选的,特别是在 Spring Data REST 的情况下?

例如,我想将一个非常相似的搜索绑定到相同的资源路径。 现在要做到这一点,我需要如下内容:

@RestResource(path = "driver", rel = "byDriver")
List<Bar> findByDriverId(@Param("id") String id, Pageable pageable);

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(@Param("id") String id, @Param("start") Date start,
        @Param("end") Date end, Pageable pageable);

这给了我:

byDriver: {
  href: "http://localhost:8080/foo/search/driver{?id,page,size,sort}",
},
byDriverAndSpan: {
  href: "http://localhost:8080/foo/search/driverAndSpan{?id,start,end,page,size,sort}",
}

想要的是能够看到类似于以下路径的内容,其中startend是可选参数,而不是在我的 Repository 中定义多个方法。

byDriverAndSpan: {
  href: "http://localhost:8080/foo/search/driverAndSpan{?id,*start,*end,page,size,sort}",
}

这可能看起来像:

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(@Param("id") String id, @Param(value = "start", optional = true) Date start,
        @Param(value = "end", optional = true) Date end, Pageable pageable);

也许您可以将“main”函数定义为default ,该函数将委托给其他函数。 像这样的东西

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
default List<Bar> findByDriverIdAndOptionalStartTimeGreaterThanEqualAndOptionalEndTimeLessThanEqual(@Param("id") String id, @Param(value = "start", optional = true) Date start,
        @Param(value = "end", optional = true) Date end, Pageable pageable) {
   if(start != null && end != null) {
      return findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(id, start, end, pageable);
   }
   return findByDriverId(id, pageable);
}

我觉得你甚至可以使用Optional作为参数类型,然后你可以使用函数重载

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
default List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(
@Param("id") String id, @Param(value = "start") Optional<Date> start,
        @Param(value = "end") Optional<Date> end, Pageable pageable) {
   if (!start.isEmpty() && !end.isEmpty()) {
      return findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(id, start.get(), end.get(), pageable);
   }
   return findByDriverId(id, pageable);
}

List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(String id, Date start, Date end, Pageable pageable);

请注意,在这种情况下,您不应公开其他端点,而应仅公开此默认方法。

不,目前不支持此功能。 如果是这样,就会有歧义的风险。 可能存在传入 url 匹配超过 1 个@RestResource

为了从 Java 的角度进行解释,假设我们可以定义两种方法:

getPerson(String firstName, int age);

getPerson(String firstName, {Optional} int age, int phoneNumber);

当有人打算调用第二种方法时会出现问题,而不是提供年龄,而是映射到第一种方法,并将 phoneNumber 作为年龄读取。

正如 UserF40 所说,这不受支持。 我们遇到了类似的问题,并通过根据提供的 Optional 参数动态构建查询来解决它。

您可以使用 Criteria API 来实现这一点,或者通过检查存在哪些参数在另一个服务类中动态构建 SQL。

使用 org.springframework.data.jpa.repository.JpaSpecificationExecutor;`

第 1 步:在您的 JPA 存储库中实现JpaSpecificationExecutor

前任:

public interface TicketRepo extends JpaRepository<Ticket, Long>, JpaSpecificationExecutor<Ticket> {

第 2 步现在根据可选参数获取票证,您可以使用 CriteriaBuilder 构建规范查询

前任:

public Specification<Ticket> getTicketQuery(Integer domainId, Calendar startDate, Calendar endDate, Integer gameId, Integer drawId) {
    return (root, query, criteriaBuilder) -> {
        List<Predicate> predicates = new ArrayList<>();

        predicates.add(criteriaBuilder.equal(root.get("domainId"), domainId));
        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createdAt"), startDate));
        predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createdAt"), endDate));

        if (gameId != null) {
            predicates.add(criteriaBuilder.equal(root.get("gameId"), gameId));
        }

        return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
    };
}

第 3 步:将 Specification 实例传递给 jpaRepo.findAll(specification),它将返回您的实体对象列表(运行示例中的票证)

ticketRepo.findAll(specification); // Pass output of function in step 2 to findAll

@Param 中有一个“ required ”参数选项可供您使用。

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")

列出 findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(@Param("id") String id, @Param(value = "start", required = false) 日期开始,@Param(value = "end", required = false) 日期结束,Pageable pageable);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM