Spring Data JPA实现分页多条件查询2

之前写过一篇博客
Spring Data JPA 使用JpaSpecificationExecutor实现多条件查询(分页查询和非分页查询)

然后发现还有其他两种写法,会更简便一些。

1、使用JPA自带的findByXxx接口
这种方法其实还比较方便,除了如果字段多的话findByXxx这个方法的名字会很长很长很长…
Containing的用法与like一致.

示例:
顺便说明一下default方法:
在java8以后,接口中可以添加使用default或者static修饰的方法,在这里我们只讨论default方法,default修饰方法只能在接口中使用,在接口中被default标记的方法为普通方法,可以直接写方法体。
实现类会继承接口中的default方法。

@Repository
public interface UserRepository extends JpaRepository<UserDO,Long> {

    Page<UserDO> findByUsernameContainingAndUserPasswordContaining(String username, String password, Pageable pageable);

    default Page<UserDO> searchUserByCondition(String username, String password, Pageable pageable){
        if(username == null){
            username = "";
        }
        if(password == null){
            password = "";
        }
        return findByUsernameContainingAndUserPasswordContaining(username, password, pageable);
    }

}

写个类测试一下:
注意要加上注解@RunWith(SpringRunner.class),有了这个注解@Autowired注入的类才能实例化到spring容器中,自动注入才能生效,如果不加这一行会报错NullPointerExecption.

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void Test1(){
        UserDO userDO = new UserDO();
        userDO.setUsername("yogi");
        userDO.setUserPassword("123456");
        userRepository.saveAndFlush(userDO);

        List<UserDO> userDOList = userRepository.searchUserByCondition("yog",null, PageRequest.of(0,10)).getContent();

        System.out.println(userDOList.size());
    }

}

2、使用ExampleMatcher

@Repository
public interface UserRepository extends JpaRepository<UserDO,Long> {

    default Page<UserDO> searchUserByCondition2(UserDO userDO, Pageable pageable){
        if (StringUtils.isEmpty(userDO.getUserPassword())) {
            // 对于数据库中允许为空的字段,需要设置null值,否则传入双引号会被判断成有值
            userDO.setUserPassword(null);
        }
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withIgnoreNullValues()
                .withIgnoreCase(false)
                .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("userPassword", ExampleMatcher.GenericPropertyMatchers.contains())
                .withIgnorePaths("userId", "userPhone");//忽略属性
        Example<UserDO> userDOExample = Example.of(userDO, matcher);
        return this.findAll(userDOExample,pageable);
    }

}

方法如下:

方法含义
caseSensitive()大小写敏感
ignoreCase()忽略大小写
contains()模糊匹配,%{str}%
startsWith()匹配起始字符串,{str}%
endsWith()匹配结尾字符串,%{str}
exact()精确匹配字符串
reges()将字符串作为正则表达式进行匹配

注意一下当使用完全匹配.exact()时,参数为String类型时,传参时如果传""(空字符串),并不是不进行筛选,而是会筛选"",结果极有可能查询结果为空。
要解决这个问题,也可以在之前对需要完全匹配的属性做出如下设置:

if (StringUtils.isEmpty(userDO.getXxx())) {
    userDO.setXxx(null);
}

此时该属性需要完全匹配,并当传入""时会不进行筛选,而是查出全部。


版权声明:本文为yogima原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。