Spring Data JPA:当Collection类型的存储库方法参数为空时,如何返回空结果? [英] Spring Data JPA: how to return empty result when repository method parameter of Collection type is empty?
问题描述
我正在使用Spring Data JPA v1.10.2还有一个用例:
I'm using Spring Data JPA v1.10.2 And there's a use-case:
ClientDao.java
:
List<Client> getClientsByUnitsIn(@NonNull Collection<Unit> units);
此方法会生成如下所示的SQL查询:
This method generates an SQL query like this one:
SELECT * FROM clients WHERE units in (?1)
当我为存储库方法添加 @Query
批注时,也有类似情况:
There's a similar case when I add @Query
annotation for the repository method:
@Query("SELECT c FROM Client c WHERE c.unit IN (?1)")
List<Client> getSpecificClients(@NonNull Collection<Unit> units)
但是在许多情况下,参数 units
可能为空.在这种情况下,该方法应该返回空结果,但只会失败,并显示一条有关错误SQL语句的消息.
But in many cases parameter units
may be empty. And in such cases the method should return empty result, but it just fail with a message about an erroneous SQL statement.
我使用一种解决方法:像这样向存储库添加默认方法:
I use a workaround: adding a default method to the repository like this one:
default List<Client> getSpecificClientsOrEmpty(@NonNull Collection<Unit> units){
if (units.isEmpty) {
return emptyList();
}
return getSpecificClients(units);
}
但是我不喜欢这种解决方法:
But I don't like this workaround:
- 我必须为每种情况创建一个额外的方法
- 我必须检查代码中是否仅使用默认方法,因为没有编译时检查,如果我错过了某些使用,则会得到运行时异常.
有人有更好的解决方案吗?
Does anybody have a better solution?
推荐答案
1)在 getSpecificClients()
存储库实现中使用样板代码编写您自己的查询:
1) Write your own query with the boiler plate code in the getSpecificClients()
repository implementation :
public List<Client> getSpecificClients(@NonNull Collection<Unit> units){
if (units.isEmpty()) {
return emptyList();
}
return em.createQuery("SELECT c FROM Client c WHERE c.unit IN (?1)", Unit.class)
.setParameter(1, units)
.getResultList();
}
如果此预处理在存储库中不常见,则应采用这种方式.
这有点冗长,但在少数情况下仍然可以接受.
If this pre-processing is a uncommon requirement in your repository, this way should be favored.
It is a little verbose way but it is still acceptable for a handful of cases.
2)用AOP横向制作.
定义 Aspect
进行此处理,然后再使用所需的每种方法:
2) Make it in a transverse way with AOP.
Define a Aspect
to do this processing before each method you need :
if (units.isEmpty) {
return emptyList();
}
请注意,只有在预处理要求经常发生的情况下才应使用这种方法,因为这会增加应用程序的复杂性和常规设置.
Note that this way should be used only if the pre-processing requirement occurs frequently enough as it increases the application complexity and the general setup.
3)您可以在基本接口存储库中创建一个通用的默认方法,该方法接受 Function
作为参数,以便能够将要执行的任何方法传递给该方法:
3) You could create a generic default method in a base interface repository that accepts a Function
as parameter to be able to passe to the method any method to execute :
@SuppressWarnings("unchecked")
default<T, U> List<U> selectWithIn(Collection<T> valueForInClause, Function<Collection<T>, List<U>> function) {
if (valueForInClause.isEmpty()) {
return new ArrayList<U>();
}
return function.apply(valueForInClause);
}
在 ClientDAO
类中,您仍然需要这个:
In ClientDAO
class you would have still this one :
@Query("SELECT c FROM Client c WHERE c.unit IN (?1)")
List<Client> getSpecificClients(@NonNull Collection<Unit> units)
在DAO的客户端代码中,您可以通过以下方式调用selectWithIn()方法:
And in the client code of the DAO you could invoke the selectWithIn() method in this way :
private ClientDAO clientDAO;
...
List<Unit> units = ...;
List<Client> clients = clientDAO.selectWithIn(units, (o) -> clientDAO.getSpecificClients(o));
不太冗长,它节省了一些代码行,但是我不喜欢这种方式,因为它使DAO客户端类的单元测试更加复杂.
It is not too much verbose, it spares some code lines but I don't like really this way as it makes a little more complex unit tests of the DAO client classes.
这篇关于Spring Data JPA:当Collection类型的存储库方法参数为空时,如何返回空结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!