我可以创建一个通用的 @Query 来检测 URL 中的哪些参数不为空,并仅使用 Spring 进行搜索吗?
Can I create a generic @Query that detects which parameters from URL are not null and make a search only by them with Spring?
我能否创建一个通用的 @Query 来检测 URL 中的哪些参数不为空,并仅通过它们进行搜索,而不是为每个参数与 Spring 框架组合创建一个方法?
例如:我的URL中有两个参数;我只想进行一个查询,从我的 URL 中检测非空参数并将它们传递给我的查询,忽略空值(而不是为不同的参数组合创建大量 if/else 和不同的查询) .
我创建了这段代码,其中 return 是一个基于用户在 URL 中传递的 NOT-NULL 参数的国家/地区列表。因为我有 4 个参数,所以所有的可能性都会导致 16 个不同的查询(因为我还有一个 findAll 方法,当没有定义参数时它会带来所有结果),而且一直创建它们很无聊。
我的控制器:
@RequestMapping(value = "/countries", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity listCountries(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "twoLetterCode", required = false) String twoLetterCode,
@RequestParam(value = "threeLetterCode", required = false) String threeLetterCode,
@RequestParam(value = "nameInPortuguese", required = false) String nameInPortuguese) {
try {
List<Country> countryList = null;
@Autowired
private CountryRepository countryRepository;
if (name != null && !name.isEmpty() && !name.equals("")) {
if (twoLetterCode != null && !twoLetterCode.isEmpty() && !twoLetterCode.equals("")) {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameTwoLetterCodeThreeLetterCodeNameInPortuguese(name, twoLetterCode, threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByNameTwoLetterCodeThreeLetterCode(name, twoLetterCode, threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameTwoLetterCodeNameInPortuguese(name, twoLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByNameTwoLetterCode(name, twoLetterCode);
}
}
} else {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameThreeLetterCodeNameInPortuguese(name, threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByNameThreeLetterCode(name, threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameNameInPortuguese(name, nameInPortuguese);
} else {
countryList = countryRepository.findByName(name);
}
}
}
} else {
if (twoLetterCode != null && !twoLetterCode.isEmpty() && !twoLetterCode.equals("")) {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByTwoLetterCodeThreeLetterCodeNameInPortuguese(twoLetterCode, threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByTwoLetterCodeThreeLetterCode(twoLetterCode, threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByTwoLetterCodeNameInPortuguese(twoLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByTwoLetterCode(twoLetterCode);
}
}
} else {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByThreeLetterCodeNameInPortuguese(threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByThreeLetterCode(threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameInPortuguese(nameInPortuguese);
} else {
countryList = countryRepository.findAll();
}
}
}
}
if (countryList != null && !countryList.isEmpty()) {
List<CountryDTO> dtosList = modelMapper.map(countryList, new TypeToken<CountryDTO>() {}.getType());
return ResponseEntity(dtosList, HttpStatus.OK);
} else {
return ResponseEntity.status(HttpStatus.OK).body(new EmptySerializableClass());
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
我的仓库:
@Query("SELECT c FROM Country c WHERE c.name LIKE :name")
public List<Country> findByName(@Param("name") String name);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode")
public List<Country> findByTwoLetterCode(@Param("twoLetterCode") String twoLetterCode);
@Query("SELECT c FROM Country c WHERE c.threeLetterCode LIKE :threeLetterCode")
public List<Country> findByThreeLetterCode(@Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameInPortuguese(@Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode")
public List<Country> findByNameTwoLetterCode(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.threeLetterCode LIKE :threeLetterCode")
public List<Country> findByNameThreeLetterCode(@Param("name") String name, @Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findBynameInPortuguese(@Param("name") String name, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode)")
public List<Country> findByTwoLetterCodeThreeLetterCode(@Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByTwoLetterCodeNameInPortuguese(@Param("twoLetterCode") String twoLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByThreeLetterCodeNameInPortuguese(@Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode)")
public List<Country> findByNameTwoLetterCodeThreeLetterCode(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameTwoLetterCodeNameInPortuguese(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameThreeLetterCodeNameInPortuguese(@Param("name") String name, @Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByTwoLetterCodeThreeLetterCodeNameInPortuguese(@Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameTwoLetterCodeThreeLetterCodeNameInPortuguese(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c")
public List<Country> findAll();
所以,我想你们明白我的问题是什么了。与其创建数百万 if/else 和数以千计的查询来处理 URL 调用中定义的非空参数,有没有办法在 Spring 框架上 - 甚至在 JPA/Hibernate 上- 只编写一个查询来检测那些非空参数并通过它们进行搜索(如果所有参数都为空,那么只有 return 所有结果)?
你不能用 @Query
注释来做。
但是您可以使用示例查询或规范查询。
使用示例查询,您可以创建目标实体 Country
的实例,其中包含过滤值作为属性,null
包含不应被过滤的那些值。
还提供一个 ExampleMatcher
来控制应该使用哪种比较(相等、包含、不区分大小写等)。
See the documentation for details。
更灵活的是规范,您可以使用 JPA 条件 API 或使用 Querydsl 以编程方式构造 where 条件。
感谢大家,但我能做到!就这么简单:
@Query("SELECT c FROM Country c WHERE (:name is null or c.name LIKE :name)"
+ " AND (:twoLetterCode is null or c.twoLetterCode LIKE :twoLetterCode)"
+ " AND (:threeLetterCode is null or c.threeLetterCode LIKE :threeLetterCode)"
+ " AND (:nameInPortuguese is null or c.nameInPortuguese LIKE :nameInPortuguese)")
public List<Country> findCountries(
@Param("name") String name,
@Param("twoLetterCode") String twoLetterCode,
@Param("threeLetterCode") String threeLetterCode,
@Param("nameInPortuguese") String nameInPortuguese);
我能否创建一个通用的 @Query 来检测 URL 中的哪些参数不为空,并仅通过它们进行搜索,而不是为每个参数与 Spring 框架组合创建一个方法?
例如:我的URL中有两个参数;我只想进行一个查询,从我的 URL 中检测非空参数并将它们传递给我的查询,忽略空值(而不是为不同的参数组合创建大量 if/else 和不同的查询) .
我创建了这段代码,其中 return 是一个基于用户在 URL 中传递的 NOT-NULL 参数的国家/地区列表。因为我有 4 个参数,所以所有的可能性都会导致 16 个不同的查询(因为我还有一个 findAll 方法,当没有定义参数时它会带来所有结果),而且一直创建它们很无聊。
我的控制器:
@RequestMapping(value = "/countries", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity listCountries(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "twoLetterCode", required = false) String twoLetterCode,
@RequestParam(value = "threeLetterCode", required = false) String threeLetterCode,
@RequestParam(value = "nameInPortuguese", required = false) String nameInPortuguese) {
try {
List<Country> countryList = null;
@Autowired
private CountryRepository countryRepository;
if (name != null && !name.isEmpty() && !name.equals("")) {
if (twoLetterCode != null && !twoLetterCode.isEmpty() && !twoLetterCode.equals("")) {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameTwoLetterCodeThreeLetterCodeNameInPortuguese(name, twoLetterCode, threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByNameTwoLetterCodeThreeLetterCode(name, twoLetterCode, threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameTwoLetterCodeNameInPortuguese(name, twoLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByNameTwoLetterCode(name, twoLetterCode);
}
}
} else {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameThreeLetterCodeNameInPortuguese(name, threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByNameThreeLetterCode(name, threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameNameInPortuguese(name, nameInPortuguese);
} else {
countryList = countryRepository.findByName(name);
}
}
}
} else {
if (twoLetterCode != null && !twoLetterCode.isEmpty() && !twoLetterCode.equals("")) {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByTwoLetterCodeThreeLetterCodeNameInPortuguese(twoLetterCode, threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByTwoLetterCodeThreeLetterCode(twoLetterCode, threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByTwoLetterCodeNameInPortuguese(twoLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByTwoLetterCode(twoLetterCode);
}
}
} else {
if (threeLetterCode != null && !threeLetterCode.isEmpty() && !threeLetterCode.equals("")) {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByThreeLetterCodeNameInPortuguese(threeLetterCode, nameInPortuguese);
} else {
countryList = countryRepository.findByThreeLetterCode(threeLetterCode);
}
} else {
if (nameInPortuguese != null && !nameInPortuguese.isEmpty() && !nameInPortuguese.equals("")) {
countryList = countryRepository.findByNameInPortuguese(nameInPortuguese);
} else {
countryList = countryRepository.findAll();
}
}
}
}
if (countryList != null && !countryList.isEmpty()) {
List<CountryDTO> dtosList = modelMapper.map(countryList, new TypeToken<CountryDTO>() {}.getType());
return ResponseEntity(dtosList, HttpStatus.OK);
} else {
return ResponseEntity.status(HttpStatus.OK).body(new EmptySerializableClass());
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
我的仓库:
@Query("SELECT c FROM Country c WHERE c.name LIKE :name")
public List<Country> findByName(@Param("name") String name);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode")
public List<Country> findByTwoLetterCode(@Param("twoLetterCode") String twoLetterCode);
@Query("SELECT c FROM Country c WHERE c.threeLetterCode LIKE :threeLetterCode")
public List<Country> findByThreeLetterCode(@Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameInPortuguese(@Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode")
public List<Country> findByNameTwoLetterCode(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.threeLetterCode LIKE :threeLetterCode")
public List<Country> findByNameThreeLetterCode(@Param("name") String name, @Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findBynameInPortuguese(@Param("name") String name, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode)")
public List<Country> findByTwoLetterCodeThreeLetterCode(@Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByTwoLetterCodeNameInPortuguese(@Param("twoLetterCode") String twoLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByThreeLetterCodeNameInPortuguese(@Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode)")
public List<Country> findByNameTwoLetterCodeThreeLetterCode(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameTwoLetterCodeNameInPortuguese(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameThreeLetterCodeNameInPortuguese(@Param("name") String name, @Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByTwoLetterCodeThreeLetterCodeNameInPortuguese(@Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c WHERE c.name LIKE :name AND c.twoLetterCode LIKE :twoLetterCode AND c.threeLetterCode LIKE :threeLetterCode AND c.nameInPortuguese LIKE :nameInPortuguese")
public List<Country> findByNameTwoLetterCodeThreeLetterCodeNameInPortuguese(@Param("name") String name, @Param("twoLetterCode") String twoLetterCode, @Param("threeLetterCode") String threeLetterCode, @Param("nameInPortuguese") String nameInPortuguese);
@Query("SELECT c FROM Country c")
public List<Country> findAll();
所以,我想你们明白我的问题是什么了。与其创建数百万 if/else 和数以千计的查询来处理 URL 调用中定义的非空参数,有没有办法在 Spring 框架上 - 甚至在 JPA/Hibernate 上- 只编写一个查询来检测那些非空参数并通过它们进行搜索(如果所有参数都为空,那么只有 return 所有结果)?
你不能用 @Query
注释来做。
但是您可以使用示例查询或规范查询。
使用示例查询,您可以创建目标实体 Country
的实例,其中包含过滤值作为属性,null
包含不应被过滤的那些值。
还提供一个 ExampleMatcher
来控制应该使用哪种比较(相等、包含、不区分大小写等)。
See the documentation for details。
更灵活的是规范,您可以使用 JPA 条件 API 或使用 Querydsl 以编程方式构造 where 条件。
感谢大家,但我能做到!就这么简单:
@Query("SELECT c FROM Country c WHERE (:name is null or c.name LIKE :name)"
+ " AND (:twoLetterCode is null or c.twoLetterCode LIKE :twoLetterCode)"
+ " AND (:threeLetterCode is null or c.threeLetterCode LIKE :threeLetterCode)"
+ " AND (:nameInPortuguese is null or c.nameInPortuguese LIKE :nameInPortuguese)")
public List<Country> findCountries(
@Param("name") String name,
@Param("twoLetterCode") String twoLetterCode,
@Param("threeLetterCode") String threeLetterCode,
@Param("nameInPortuguese") String nameInPortuguese);