我正在使用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);
}
但我不喜欢这种解决方法:
有人有更好的解决方案吗?
答案 0 :(得分:2)
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)您可以在基本接口存储库中创建一个通用的默认方法,该存储库接受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客户端类进行了一些更复杂的单元测试。