Java Spring REST API 处理许多可选参数

标签 java mysql rest spring-boot spring-data-jpa

出于教学目的,我目前正在处理一个 Spring Boot REST API 项目。我有一个相当大的表,其中有 22 列加载到 MySQL 数据库中,我试图让用户能够按多列过滤结果(在本示例中假设为 6)。

我目前正在扩展一个存储库,并已初始化方法,例如 findByParam1 和 findByParam2 以及 findByParam1OrderByParam2Desc 等,并已验证它们是否按预期工作。我想问你们的问题是最好的方法是让用户能够利用所有 6 个可选的 RequestParam,而无需编写大量的条件/存储库方法变体。例如,我想让用户能够点击 url home/get-data/ 获取所有结果,home/get-data?param1=xx 以基于 param1 进行过滤,并且可能, home/get-data?param1=xx¶m2=yy...¶m6=zz 过滤所有可选参数。

作为引用,下面是我的 Controller 的相关部分(大致)。

@RequestMapping(value = "/get-data", method = RequestMethod.GET)
public List<SomeEntity> getData(@RequestParam Map<String, String> params) {
    String p1 = params.get("param1");
    if(p1 != null) {
        return this.someRepository.findByParam1(p1);
    }
    return this.someRepository.findAll();
}

到目前为止,我的问题是我处理这件事的方式意味着我基本上需要 n!我的存储库中支持此功能的方法数量 n 等于我要过滤的字段/列的数量。有没有更好的方法来处理这个问题,也许我正在“就地”过滤存储库,这样我就可以简单地“就地”过滤,因为我检查 map 以查看用户确实填充了哪些过滤器?

编辑:所以我目前正在实现一个可能与 J. West 下面的评论相关的“hacky”解决方案。我假设用户将在请求 URL 中指定所有 n 个参数,如果他们不指定(例如,他们指定 p1-p4 但不指定 p5 和 p6),我生成的 SQL 只匹配语句到 LIKE '%'非包含参数。它看起来像……

@Query("select u from User u where u.p1 = :p1 and u.p2 = :p2 ... and u.p6 = :p6") 
List<User> findWithComplicatedQueryAndSuch;

在 Controller 中,我会检测映射中的 p5 和 p6 是否为空,如果是,只需将它们更改为字符串“%”。我确信有一种更精确、更直观的方法可以做到这一点,尽管我还没有找到任何类似的方法。

最佳答案

您可以使用 JpaSpecificationExecutor 和自定义 Specification 轻松完成此操作:https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

我会用包含所有可选获取参数的 DTO 替换 HashMap,然后基于该 DTO 构建规范,显然您也可以保留 HashMap 并基于它构建规范。

基本上:

public class VehicleFilter implements Specification<Vehicle>
{
    private String art;
    private String userId;
    private String vehicle;
    private String identifier;

    @Override
    public Predicate toPredicate(Root<Vehicle> root, CriteriaQuery<?> query, CriteriaBuilder cb)
    {
        ArrayList<Predicate> predicates = new ArrayList<>();

        if (StringUtils.isNotBlank(art))
        {
            predicates.add(cb.equal(root.get("art"), art));
        }
        if (StringUtils.isNotBlank(userId))
        {
            predicates.add(cb.equal(root.get("userId"), userId));
        }
        if (StringUtils.isNotBlank(vehicle))
        {
            predicates.add(cb.equal(root.get("vehicle"), vehicle));
        }
        if (StringUtils.isNotBlank(identifier))
        {
            predicates.add(cb.equal(root.get("identifier"), fab));
        }

        return predicates.size() <= 0 ? null : cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }

// getter & setter
}

和 Controller :

@RequestMapping(value = "/{ticket}/count", method = RequestMethod.GET)
public long getItemsCount(
    @PathVariable String ticket,
    VehicleFilter filter,
    HttpServletRequest request
) throws Exception
{
    return vehicleService.getCount(filter);
}

服务:

@Override
public long getCount(VehicleFilter filter)
{
    return vehicleRepository.count(filter);
}

存储库:

@Repository
public interface VehicleRepository extends JpaRepository<Vehicle, Integer>, JpaSpecificationExecutor<Vehicle>
{
}

只是一个根据公司代码改编的简单示例,您明白了!

关于Java Spring REST API 处理许多可选参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41068956/

相关文章:

Java REST API : Returning Multiple objects from API Method

spring - Oauth2 Spring 中的更改响应

java - 我如何让 spring 为所有 Controller / Action 设置某些变量

java - 将 ZIP 转换为字节数组而不将输出保存到文件

java - ListView 分隔符未分隔项目

php - 在 PHP 中为用户创建 Excel 文件

java - Mockito:如何部分使用 @InjectMocks-Annotation 进行 MockMvc 测试?

mysql - Phpmyadmin 导出问题 : count(): Parameter must be an array or an object that implements Countable

php - Zend框架2 : How to write custom query using tablegateway

python - 如何通过 python 在线连接到 quickbooks?