[英]Best way to use query params in Spring Boot
我在代码中有我的 JPA 存储库,它有多个 findByColumn 方法用于快速查找。
很少有像 findByColumn1AndColumn2AndColumn3 这样的多列的 findBy 子句,还有更多像提到的多列或多列的组合。
我的问题是目前我希望我的客户只对所有选择/获取操作使用一个端点,这些操作期望每一列的 RequestParam,如果他没有在请求端点上输入任何预期的列值,我将默认设置为“NA”,然后我使用 if 子句来识别所有传入的字段参数,然后调用受尊重的存储库端点。
我现在的问题是由于在同一个端点中添加多个新列请求我的 if 子句如果变得狂热,我相信足够的代码不会对其他团队成员阅读友好。
任何人都可以建议如何在 Spring Boot 应用程序上实现这个动态查询部分。
我的控制器代码片段如下所示:
@GetMapping("/getdata")
public ResponseEntity<Page<PojoTbl>> getDataFromDB(
@PageableDefault(page = 0, size = 20) @SortDefault.SortDefaults({
@SortDefault(sort = "id", direction = Sort.Direction.DESC) }) Pageable pageable,
@RequestParam(value = "col1", required = false, defaultValue = "NA") String col1,
@RequestParam(value = "col2", required = false, defaultValue = "NA") String col2,
@RequestParam(value = "col3", required = false, defaultValue = "NA") String col3,
@RequestParam(value = "col4", required = false, defaultValue = "NA") String col4,
@RequestParam(value = "col5", required = false, defaultValue = "NA") String col5,
@RequestParam(value = "col6", required = false, defaultValue = "NA") String col6,
@RequestParam(value = "col7", required = false, defaultValue = "NA") String col7,
@RequestParam(value = "col8", required = false, defaultValue = "NA") String col8,
@RequestParam(value = "id", required = false) Long id) {
Page<PojoTbl> selectedRecords = myService.findDataFromDB(col1,
col2, col3, col4, col5, col6, col7, id,
col8, pageable);
return ResponseEntity.ok(selectedRecords);
}
后端服务层同样看起来像这样:
public Page<PojoTbl> findDataFromDB(String col1, String col2,
String col3, String col4, String col5, String col6,
String col7, Long id, String col8, Pageable pageable) {
Page<PojoTbl> selectedRecords = null;
if (col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findAll(pageable);
} else if (col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && !col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol8IgnoreCase(col8, pageable);
} else if (!col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol1IgnoreCase(col1, pageable);
} else if (col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && !col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol5IgnoreCase(col5, pageable);
} else if (col1.equals("NA") && !col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol2IgnoreCase(col2, pageable);
} else if (col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && !col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol6IgnoreCase(col6, pageable);
} else if (col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && !col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol7IgnoreCase(col7, pageable);
} else if (col1.equals("NA") && col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& !Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findById(id, pageable);
} else if (!col1.equals("NA") && !col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol1Andcol2IgnoreCase(col1, col2,
pageable);
} else if (!col1.equals("NA") && !col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && !col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol1Andcol2Andcol5IgnoreCase(col1,
col2, col5, pageable);
} else if (!col1.equals("NA") && !col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && !col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository.findBycol1Andcol2Andcol6IgnoreCase(col1,
col2, col6, pageable);
} else if (!col1.equals("NA") && !col2.equals("NA") && col3.equals("NA")
&& col4.equals("NA") && !col6.equals("NA") && !col7.equals("NA")
&& Objects.isNull(id) && col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository
.findBycol1Andcol2Andcol6Andcol7IgnoreCase(col1, col2,
col6, col7, pageable);
} else if (!col1.equals("NA") && !col2.equals("NA") && !col3.equals("NA")
&& !col4.equals("NA") && !col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && !col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository
.findBycol1Andcol2Andcol3Andcol4Andcol6IgnoreCase(
col1, col2, col3, col4, col6, pageable);
} else if (!col1.equals("NA") && !col2.equals("NA") && !col3.equals("NA")
&& !col4.equals("NA") && col6.equals("NA") && col7.equals("NA")
&& Objects.isNull(id) && !col5.equals("NA") && col8.equals("NA")) {
selectedRecords = tableJpaRepository
.findBycol1Andcol2Andcol3Andcol4Andcol5IgnoreCase(
col1, col2, col3, col4, col5, pageable);
}
return selectedRecords;
}
看看我在服务层创建的复杂性,这将在未来的版本中产生问题,因为由于许多检查单个 if 语句,代码看起来很混乱。
希望有人可以指导我了解可以降低代码复杂性的最佳实践。
尽管您可以按照评论中的建议使用规范,但您可以尝试使用@Query
注释进行自定义查询。
public interface PersonRepository extends JpaRepository<PojoTbl, Integer> {
@Query("select p from PojoTbj p where " +
"(p.col1 like ?1 or ?1 is null) and " +
"(p.col2 like ?2 or ?2 is null) and " +
"(p.col3 like ?3 or ?3 is null) and " +
"(p.id = ?4 or id is null)"
)
Page<PojoTbl> findByParams(String param1, String param2, String param3, Long id, Pageable pageable)
}
使用?1 is null
类的条件允许您为不想在查询中使用的参数传递null
。 所以你不再需要"NA"
值了。
public ResponseEntity<Page<PojoTbl>> getDataFromDB(
@PageableDefault(page = 0, size = 20) @SortDefault.SortDefaults({
@SortDefault(sort = "id", direction = Sort.Direction.DESC) }) Pageable pageable,
@RequestParam(required = false) String col1,
@RequestParam(required = false) String col2,
@RequestParam(required = false) String col3,
@RequestParam(value = "id", required = false, defaultValue=null) Long id) {
Page<PojoTbl> selectedRecords = myService.findDataFromDB(col1,
col2, col3, id, pageable);
return ResponseEntity.ok(selectedRecords);
}
@Query
接受任何有效的 JPQL 查询。 这意味着您可以使用任何 JPQL 函数。 例如,如果您需要忽略大小写,您可以使用upper
函数:
@Query("select p from PojoTbj p where " +
"(upper(p.col1) like upper(?1) or ?1 is null))
通过您的存储库方法,我了解到您正在对可用字段进行基本的findBy 。
查看示例查询 (QBE) : 文档
本质上,您正在向实体填充所有现有字段并要求返回示例类型。
虽然这种方法有助于您的案例的动态性质,但它有一些限制,如上面的文档链接中所述。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.