Spring数据JPA和可以为null的参数

时间:2015-05-13 15:38:51

标签: java parameters null spring-data-jpa

我的理解是,使用Spring数据JPA我不能有一个查询方法来获取列等于给定的非null方法参数的所有行,并使用相同的方法来获取该列为NULL的所有行参数为空。

这是对的吗?

所以我必须在我的JAVA代码中区分它,我必须使用一个单独的查询方法明确要求空值,如下例所示?

// Query methods
List<Something> findByParameter(Parameter parameter);
List<Something> findByParameterIsNull();

...

List<Something> result = new ArrayList<>();

if (parameter == null)
  result = findByParameterIsNull();
else
  result = findByParameter(parameter);

这很糟糕,如果我有4个参数可以为null并且必须编码16种不同的查询方法。

6 个答案:

答案 0 :(得分:16)

你是对的。

已经发出请求以支持更好地处理空参数。 https://jira.spring.io/browse/DATAJPA-121

在您的情况下,我建议您编写存储库实现并使用自定义CriteriaQuery来处理您的案例。

此外,您可以使用@Query语法{/ 3}}注释{/ 3}}

@Query("[...] where :parameter is null"
public List<Something> getSomethingWithNullParameter();

修改

自Spring数据jpa 2.0以来,spring现在支持@Nullable注释。这有助于处理传递的null参数。

来自is null

  

@Nullable - 用于参数或返回值,可以为null。

答案 1 :(得分:10)

似乎Query by Example可能就是您所需要的。

按示例查询是Spring Data中的一项新功能(since version Hopper,2016年4月),它允许用这样的代码创建简单的动态查询

Person person = new Person();                          
person.setFirstname("Dave");                           

ExampleMatcher matcher = ExampleMatcher.matching()     
  .withIncludeNullValues();                        

Example<Person> example = Example.of(person, matcher);

personRepository.count(example);
personRepository.findOne(example);
personRepository.findAll(example);

count/findOne/findAll的实例作为参数(其中一些也采用排序/分页参数)的方法org.springframework.data.domain.Example来自org.springframework.data.repository.query.QueryByExampleExecutor<T>接口,由{{{}}扩展1}}接口。

简而言之,所有org.springframework.data.jpa.repository.JpaRepository<T, ID extends Serializable>实例现在都有这些方法。

答案 2 :(得分:5)

我发现了一些东西...如果您将参数放在这样的jpa方法中

@Param("value") String value,

然后它可以为空,并且在查询中您将具有以下条件:

(table.value = :value OR :value IS NULL)

如果该值为null,则将自动返回true;如果不为null,则将在表中搜索该值。

答案 3 :(得分:4)

今天截至2018年6月,通过查看https://jira.spring.io/browse/DATAJPA-121,如果您的参数为空,查询将自动形成is null

我在我的项目中做到了,这是真的:

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.0.7.RELEASE'

-

public interface AccountDao extends CrudRepository<T, ID> {

    //this can accept null and it will become isNull
    public List<MyAccount> findByEmail(String email);

}

如果参数为null:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email is null

如果参数不为null:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email=?
11:02:41.623 [qtp1507181879-72] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [testing@hotmail.com] 

接下来是一个有趣的问题,一些开发人员想要更好的控制来忽略查询中的参数,如果它是null,这仍然在https://jira.spring.io/browse/DATAJPA-209中进行调查。

答案 4 :(得分:2)

虽然已经回答了该问题,并且所接受的答案与当前问题有关,但是还有另一种方法可以处理JpaRespository中的空参数。如果有人要通过在null时忽略字段并构建动态查询来进行查询,则可以将其发布在此处,因为这可以被利用。 下面的代码示例应演示相同的内容

☁  react-apollo-graphql-starter-kit [master] npm t -- --coverage /Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/stackoverflow/61928263/index.test.jsx

> react-apollo-graphql-starter-kit@1.0.0 test /Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit
> jest "--coverage" "/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/stackoverflow/61928263/index.test.jsx"

 PASS  stackoverflow/61928263/index.test.jsx
  61928263
    ✓ should pass without using mock store (35ms)

--------------------|---------|----------|---------|---------|-------------------
File                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------------|---------|----------|---------|---------|-------------------
All files           |     100 |      100 |     100 |     100 |                   
 LoadingMessage.jsx |     100 |      100 |     100 |     100 |                   
 index.jsx          |     100 |      100 |     100 |     100 |                   
 user.actions.ts    |     100 |      100 |     100 |     100 |                   
--------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.453s, estimated 4s
Ran all test suites matching /\/Users\/ldu020\/workspace\/github.com\/mrdulin\/react-apollo-graphql-starter-kit\/stackoverflow\/61928263\/index.test.jsx/i.

答案 5 :(得分:0)

在我的情况下,membershipNumber可为空,并且我已经用这种方式处理了它。这将处理所有table.membershipNumber也为null的情况。

      @Query(value = "SELECT pr FROM ABCTable pr " +
            "WHERE LOWER(pr.xyz) = LOWER(:xyz) " +
            "and LOWER(pr.subscriptionReference) = LOWER(:subscriptionReference) " +
            "and pr.billId = :billId " +
            "and ((pr.membershipNumber = :membershipId) or (pr.membershipNumber = null and :membershipId = null))")
    List<PaymentRequest> getSomething (@Param("xyz") String xyz,
                                                 @Param("subscriptionReference") String subscriptionReference,
                                                 @Param("billId") Integer billId,
                                                 @Param("membershipId") String membershipNumber);