繁体   English   中英

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,有一个用例:

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)您可以在基础接口存储库中创建一个通用的默认方法,该方法接受一个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客户端类的单元测试更加复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM