具有可选@Param的弹簧数据查询方法

2022-09-02 14:14:07

是否可以允许查询方法@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

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);

答案 1

也许你可以定义一个“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);

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


答案 2

否,目前不支持此功能。如果是这样,就会有模棱两可的风险。可能存在传入 URL 可能匹配超过 1 的情况。@RestResource

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

getPerson(String firstName, int age);

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

当有人打算调用第二种方法时,会出现问题,不是提供年龄,而是映射到第一种方法,电话号码被读取为年龄。


推荐