减少原生查询命名参数,简化Repository方法调用
解决方案:使用DTO封装筛选参数
通过创建专门的DTO类封装所有筛选参数,将Repository方法的多参数改为单参数传入,优化调用体验,同时保留原生查询写法,无需使用Criteria API。
1. 创建筛选参数DTO类
把所有需要传入的筛选参数(含枚举类型)封装到一个DTO中,可借助Lombok简化代码:
import lombok.Data; @Data public class TestFilterDTO { private Long tenantId; private ExpertLevel expertLevel; private TestType testType; private Long technology; private Long category; }
如果不使用Lombok,手动编写构造器、getter和setter方法即可。
2. 修改Repository方法
将原方法的多个参数替换为DTO参数,通过@Param注解绑定,并调整原生查询中的参数引用为DTO属性:
@Query(value = testsQuery + "AND (:filter.expertLevel IS NULL OR a.expertLevel = :filter.expertLevel)" + "AND (:filter.testType IS NULL OR a.testType = :filter.testType)" + "AND (:filter.technology IS NULL OR t.id = :filter.technology)" + "AND (:filter.category IS NULL OR c.id = :filter.category)" + "GROUP BY a.id, a.name, a.duration, a.expertLevel, a.testType, c.name, j.name, t.name") List<GettestQueryItem> findAllTestsBy(@Param("filter") TestFilterDTO filter);
注:这里把原查询中的CASE语句简化为逻辑表达式,功能与原写法完全一致,可根据个人习惯选择保留原CASE写法或使用简化版。
3. 调用Repository方法
调用时只需创建DTO实例,设置需要的筛选条件(无需设置的参数保持为null),再传入方法即可:
TestFilterDTO filter = new TestFilterDTO(); filter.setTenantId(1L); filter.setExpertLevel(ExpertLevel.ADVANCED); filter.setTestType(TestType.PRACTICAL); List<GettestQueryItem> results = testRepository.findAllTestsBy(filter);
可选调整:保留必传参数单独传入
如果tenantId是必传参数,也可以将其从DTO中抽出单独作为方法参数,明确参数必要性:
@Query(value = testsQuery + "AND (:filter.expertLevel IS NULL OR a.expertLevel = :filter.expertLevel)" + "AND (:filter.testType IS NULL OR a.testType = :filter.testType)" + "AND (:filter.technology IS NULL OR t.id = :filter.technology)" + "AND (:filter.category IS NULL OR c.id = :filter.category)" + "GROUP BY a.id, a.name, a.duration, a.expertLevel, a.testType, c.name, j.name, t.name") List<GettestQueryItem> findAllTestsBy(@Param("tenantId") Long tenantId, @Param("filter") TestFilterDTO filter);
内容的提问来源于stack exchange,提问作者Ch Vamsi
相关产品推荐
相关产品推荐

