Java Spring数据JPA和可以为空的参数

Java Spring数据JPA和可以为空的参数,java,parameters,null,spring-data-jpa,Java,Parameters,Null,Spring Data Jpa,我的理解是,对于SpringDataJPA,我不能有一个查询方法来获取列等于给定的非null方法参数的所有行,也不能使用相同的方法来获取方法参数为null时该列为null的所有行 对吗 因此,我必须在JAVA代码中区分这一点,并且必须使用一个单独的查询方法显式地请求空值,如下面的示例所示 // Query methods List<Something> findByParameter(Parameter parameter); List<Something> findBy

我的理解是,对于SpringDataJPA,我不能有一个查询方法来获取列等于给定的非null方法参数的所有行,也不能使用相同的方法来获取方法参数为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);
//查询方法
列出findByParameter(参数);
列出findbyparametersnall();
...
列表结果=新建ArrayList();
if(参数==null)
结果=findbyparameterinsull();
其他的
结果=findByParameter(参数);
如果我有4个可能为空的参数,并且必须编码16种不同的查询方法,那就太糟糕了。

你说得对

已请求支持更好地处理空参数。

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

您还可以将注释与以下语法一起使用:

@Query(“[…]其中:参数为null”
公共列表getSomethingWithNullParameter();
编辑

由于Spring数据JPA2.0,Spring现在支持@Nullable注释。这有助于处理传递的null参数

从:

@Nullable–用于可以为null的参数或返回值

这可能是你需要的

示例查询是Spring Data(,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);
@Param("value") String value,
Person-Person=新的Person();
person.setFirstname(“Dave”);
ExampleMatcher matcher=ExampleMatcher.matching()
.带有includeNullValues();
例例=例例(人、匹配者);
personRepository.count(示例);
findOne(示例);
personRepository.findAll(示例);
方法
count/findOne/findAll
将org.springframework.data.domain.Example的实例作为参数(其中一些方法还采用排序/分页参数)来自
org.springframework.data.repository.query.QueryByExampleExecutor
接口,该接口由
org.springframework.data.jpa.repository.JpaRepository
接口扩展


简而言之,现在所有的
JpaRepository
实例都有这些方法。

从2018年6月起,如果您的参数为null,查询将自动形成
为null

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

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

如果参数不为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] 

接下来是一个有趣的问题,一些开发人员希望更好地控制忽略查询中的参数,如果它为空,这仍在调查中。

我发现了一些东西……如果你像这样将参数放入jpa方法中

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);
@Param("value") String value,
然后它可以为null,并且在查询中您将具有以下条件:

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

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

在我的情况下,membershipNumber可以为null,我已经这样处理了。这将处理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);

@Query(value=“从ABCTable pr中选择pr”+
其中较低(pr.xyz)=较低(:xyz)+
“和更低(pr.subscriptionReference)=更低(:subscriptionReference)”+
“和pr.billId=:billId”+
“和((pr.membershipNumber=:membershipId)或(pr.membershipNumber=null和:membershipId=null))”
列出getSomething(@Param(“xyz”)字符串xyz,
@参数(“subscriptionReference”)字符串subscriptionReference,
@参数(“billId”)整数billId,
@参数(“成员身份ID”)字符串成员身份号);

虽然已经回答了这个问题,并且接受的答案与当前问题相关,但是还有另一种方法可以处理JPareSposition中的空参数。当有人希望通过忽略空字段进行查询并生成动态查询时,可以将此作为一种手段发布到此处。 下面的代码示例应演示相同的功能

public class User{
  private String firstName;
  private String lastName;
}

import javax.persistence.criteria.Predicate;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User,Long>{

  public Page<AppUser> findAll(Specification<AppUser> user,Pageable page);

  public default Page<AppUser> findAll(User user,Pageable page){
    return findAll(search(user),page);
  }

  static Specification<User> search(User entity) {
    return (root, cq, cb) -> {
      //To ensure we start with a predicate
      Predicate predicate = cb.isTrue(cb.literal(true));
      if(entity.getFirstName() != null && !entity.getFirstName().isBlank()) {
        Predicate _predicate = cb.like(cb.lower(root.get("firstName")), "%"+entity.getFirstName().toLowerCase()+"%");
        predicate = cb.and(predicate,_predicate);
      }
      if(entity.getLastName() != null && !entity.getLastName().isBlank()) {
        Predicate _predicate = cb.like(cb.lower(root.get("lastName")), "%"+entity.getLastName().toLowerCase()+"%");
        predicate = cb.and(predicate,_predicate);
      }
      return predicate;
    }
  }
}
公共类用户{
私有字符串名;
私有字符串lastName;
}
导入javax.persistence.criteria.Predicate;
导入org.springframework.data.jpa.domain.Specification;
导入org.springframework.data.jpa.repository.JpaRepository;
公共接口用户存储库扩展了JpaRepository{
公共页面findAll(规范用户,可分页页面);
公共默认页面findAll(用户,可分页页面){
返回findAll(搜索(用户),第页);
}
静态规范搜索(用户实体){
返回(根、cq、cb)->{
//为了确保我们从谓词开始
谓词=cb.isTrue(cb.literal(true));
if(entity.getFirstName()!=null&&!entity.getFirstName().isBlank()){
谓词_Predicate=cb.like(cb.lower(root.get(“firstName”)),“%”+entity.getFirstName().toLowerCase()+“%”;
谓词=cb.and(谓词,_谓词);
}
if(entity.getLastName()!=null&&!entity.getLastName().isBlank()){
谓词_Predicate=cb.like(cb.lower(root.get(“lastName”)),“%”+entity.getLastName().toLowerCase()+“%”;
谓词=cb.and(谓词,_谓词);
}
返回谓词;
}
}
}

我扩展了答案:当使用Spring数据JPA
@Query
注释时,您必须使用两种单独的查询方法。一种用于处理空值,另一种用于非空值。但是当使用由Spring数据解析器解析的查询方法时(无
@Query
注释),可以用一个方法处理空值或非空值。@Query
:参数为nul
public class User{
  private String firstName;
  private String lastName;
}

import javax.persistence.criteria.Predicate;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User,Long>{

  public Page<AppUser> findAll(Specification<AppUser> user,Pageable page);

  public default Page<AppUser> findAll(User user,Pageable page){
    return findAll(search(user),page);
  }

  static Specification<User> search(User entity) {
    return (root, cq, cb) -> {
      //To ensure we start with a predicate
      Predicate predicate = cb.isTrue(cb.literal(true));
      if(entity.getFirstName() != null && !entity.getFirstName().isBlank()) {
        Predicate _predicate = cb.like(cb.lower(root.get("firstName")), "%"+entity.getFirstName().toLowerCase()+"%");
        predicate = cb.and(predicate,_predicate);
      }
      if(entity.getLastName() != null && !entity.getLastName().isBlank()) {
        Predicate _predicate = cb.like(cb.lower(root.get("lastName")), "%"+entity.getLastName().toLowerCase()+"%");
        predicate = cb.and(predicate,_predicate);
      }
      return predicate;
    }
  }
}