我的理解是,使用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种不同的查询方法。
答案 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);