java - Best way to use query params in Spring Boot
问题描述
I have my JPA repository in place in code which is having multiple findByColumn method for fast lookup.
and few findBy clause with multiple columns like findByColumn1AndColumn2AndColumn3 and many more like or combination of multiple columns like mentioned.
My question is currently I expect my client to use just one endpoint for all the select/fetch operation which expect the RequestParam for each column and if he does not enter any expected column value on the request endpoint I set default as "NA" and I use if clause to identified all the incoming fields params and then call the respected repository endpoint.
I problem is now due to adding multiple new columns in the same endpoint request my if clause if become craze and I am confident enough code will not be user friendly for other team member to read.
Can anyone suggestion how to achieve this dynamic query part on the spring boot app.
My Controller Code snippet look like this:
@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);
}
Back-end service layer for the same look like this:
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;
}
See the complexity i have created in the service layer, this will going to create problem in future release as code looks messy due to many check in single if statement.
Hope someone can guide me on the best practices which can reduce the code complexity here.
解决方案
尽管您可以使用注释中建议的规范,但您可以尝试使用注释的自定义查询@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))
推荐阅读
- delphi - 新记录的 Delphi Master Detail 级联 ID 不能与 AutoGenerateValue 结合使用
- vue.js - 在没有 npm install 或 webpack 的情况下导入 vuejs 组件
- json - Codable 函数有什么问题?
- paypal - 贝宝专业 + 红衣主教。在哪里可以找到测试凭证?
- oauth-2.0 - {"error":"invalid_client","message":"客户端认证失败"}
- laravel - JWTAuth::fromUser($newRegistredUser) 给我当前登录用户的令牌
- c++ - 什么是 Linux 等效的 Visual Studio 的“发布模式下的构建代码”?
- apache-kafka - 我想通过一次又一次地调用它来制作一个小数据流
- python - python的%(模)运算符什么时候工作得更快?有没有特殊的数字、案例?质数?
- python - 显示没有关联图像映射的颜色条