问题由来:
刚开始使用springdata的时候,只会用findByName这样的简单查询,这样写dao层确实非常的快,但是在我们做筛选功能的时候,这样的查询似乎很难满足我们的需求,但是都已经用上的springdata又不想再去写mybatis这样在xml里面判断是否为Null。
解决方案:
1.
Example,用example可以最快速的完成支持所有参数的筛选功能,像这样的代码:
@Test
public void contextLoads() {
User user = new User();
user.setUsername("y");
user.setAddress("sh");
user.setPassword("admin");
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("username", ExampleMatcher.GenericPropertyMatchers.startsWith())//模糊查询匹配开头,即{username}%
.withMatcher("address" ,ExampleMatcher.GenericPropertyMatchers.contains())//全部模糊查询,即%{address}%
.withIgnorePaths("password")//忽略字段,即不管password是什么值都不加入查询条件
.withIgnorePaths("id"); //忽略属性:是否关注。因为是基本类型,需要忽略掉
Example<User> example = Example.of(user ,matcher);
List<User> list = userRepository.findAll(example);
System.out.println(list);
}
Example会将为null的字段自动过滤掉,不会作为筛选条件,ExampleMatch是为了支持一些稍微复杂一些的查询,比如如果有int类型的id就需要用.withIgnorePaths()忽略掉,因为Int类型默认为0,而不是Null。
如果只是简单的字符串匹配的话,可以直接用:
Example<User> example = Example.of(user);
来构造Example。
但是使用这种方式会遇到一个问题,它没有办法实现 id > startId && id < endId 这样的操作
2.
使用@Query注解,这种方式可以直接在Repository里面写sql,但是这种方式的问题就是太麻烦了,而且非常容易出错,扩展性也很差,还不如直接用mybatis。
3.
使用Criteria查询,这是springdata中最强的使用方式了,所有的场景应该都能完成。
首先Repository要继承JpaSpecificationExecutor;
public interface UserRepository extends JpaRepository<UpgradeScheduleView,Integer>, JpaSpecificationExecutor {
}
然后就是构造动态查询:
public Page<UpgradeScheduleView> getPageUpgradeScheduleView(UpgradeViewSelector upgradeViewSelector, int pageNumber, int pageSize) {
Specification querySpeci = new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = Lists.newArrayList();
if(!StringUtils.isEmpty(upgradeViewSelector.getTaskName())) {
predicates.add(criteriaBuilder
.like(root.get("taskName"), "%" + upgradeViewSelector.getTaskName() + "%"));
}
if(!StringUtils.isEmpty(upgradeViewSelector.getTboxId())){
predicates.add(criteriaBuilder
.like(root.get("tboxId"), "%" + upgradeViewSelector.getTboxId() + "%"));
}
if(null != upgradeViewSelector.getOver()){
predicates.add(criteriaBuilder.equal(root.get("over"), upgradeViewSelector.getOver()));
}
if(null != upgradeViewSelector.getFlag()){
predicates.add(criteriaBuilder.equal(root.get("flag"), upgradeViewSelector.getFlag()));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
PageRequest pageRequest = PageUtil.buildPageRequest(pageNumber, pageSize);
return upgradeScheduleViewRepository.findAll(querySpeci,pageRequest);
}
具体的可以去查看
https://www.jianshu.com/p/0939cec7e207
上面这段代码我是直接从项目中copy过来的,可以看到这里还使用PageRequest进行了分页,推荐使用PageUtil去构造PageRequest,因为发现直接new的PageRequest的页码是从0开始的,简直反人类- -