我正在使用 Spring Data JPA v1.10.2 还有一个用例:
ClientDao.java
:
List<Client> getClientsByUnitsIn(@NonNull Collection<Unit> units);
此方法生成如下 SQL 查询:
SELECT * FROM clients WHERE units in (?1)
当我为存储库方法添加 @Query
注解时,也会出现类似的情况:
@Query("SELECT c FROM Client c WHERE c.unit IN (?1)")
List<Client> getSpecificClients(@NonNull Collection<Unit> units)
但在许多情况下,参数units
可能为空。在这种情况下,该方法应该返回空结果,但它只是失败并显示有关错误 SQL 语句的消息。
我使用一种解决方法:向存储库添加默认方法,如下所示:
default List<Client> getSpecificClientsOrEmpty(@NonNull Collection<Unit> units){
if (units.isEmpty) {
return emptyList();
}
return getSpecificClients(units);
}
但我不喜欢这种解决方法:
- 我必须为每种情况创建一个额外的方法
- 我必须检查代码中是否仅使用了默认方法,因为没有编译时检查,如果我错过了某些使用,则会收到运行时异常。
有没有人有更好的解决方案?
最佳答案
1) 使用 getSpecificClients()
存储库实现中的样板代码编写您自己的查询:
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();
}
如果这种预处理在您的存储库中是不常见的要求,那么应该优先考虑这种方式。
这种方式有点冗长,但对于少数情况来说仍然可以接受。
2)用AOP横向制作。
定义一个 Aspect
在您需要的每个方法之前执行此处理:
if (units.isEmpty) {
return emptyList();
}
请注意,只有当预处理要求发生得足够频繁时才应使用这种方法,因为它会增加应用程序的复杂性和一般设置。
3) 您可以在基本接口(interface)存储库中创建一个通用默认方法,该方法接受 Function
作为参数,以便能够将任何要执行的方法传递给该方法:
@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
类中,您仍然会有这个:
@Query("SELECT c FROM Client c WHERE c.unit IN (?1)")
List<Client> getSpecificClients(@NonNull Collection<Unit> units)
在 DAO 的客户端代码中,您可以通过以下方式调用 selectWithIn() 方法:
private ClientDAO clientDAO;
...
List<Unit> units = ...;
List<Client> clients = clientDAO.selectWithIn(units, (o) -> clientDAO.getSpecificClients(o));
它并不太冗长,它节省了一些代码行,但我真的不喜欢这种方式,因为它对 DAO 客户端类进行了更复杂的单元测试。
关于java - Spring 数据JPA : how to return empty result when repository method parameter of Collection type is empty?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48071990/