Spring Data JPA:当Collection类型的存储库方法参数为空时,如何返回空结果? [英] Spring Data JPA: how to return empty result when repository method parameter of Collection type is empty?

查看:119
本文介绍了Spring Data JPA:当Collection类型的存储库方法参数为空时,如何返回空结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆