前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Data JPA中分别使用Specifications、ExampleMatcher进行查询

Spring Data JPA中分别使用Specifications、ExampleMatcher进行查询

作者头像
砒霜拌辣椒
发布2023-08-23 17:21:39
7020
发布2023-08-23 17:21:39
举报
文章被收录于专栏:HerculesHercules

1、Specifications进行查询

在一些查询条件不固定的场景下,我们需要动态去组装查询条件。在Spring Data JPA中可以通过 JpaSpecificationExecutor 接口查询。相比JPQL,其优势是类型安全,更加的面向对象。

1.1、创建Repository

需要继承 JpaSpecificationExecutor 接口。

代码语言:javascript
复制
public interface SpecificationRepository extends JpaRepository<Actor, Long>, JpaSpecificationExecutor<Actor> {

}
1.2、Service
代码语言:javascript
复制
@Service
@Transactional
@Slf4j
public class SpecificationServiceImpl implements SpecificationService {
    @Autowired
    private SpecificationRepository specificationRepository;

    @Override
    public List<Actor> findBySpecification(Long id, Integer age, Integer page, Integer pageSize) {
        Specification<Actor> specification = (Specification<Actor>) (root, criteriaQuery, criteriaBuilder) -> {
            // 查询条件的集合
            List<Predicate> list = new ArrayList<>();

            // 条件1:id字段需要大于等于指定的id
            list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("id"), (id == null || id < 0) ? 0 : id));
            // 条件2:如果指定了age,则需要相等
            if(age != null && age > 0) {
                // 字段需要和实体类中属性相同,而非表中字段
                list.add(criteriaBuilder.equal(root.get("actorAge"), age));
            }

            // 转数组
            Predicate[] predicates = new Predicate[list.size()];
            list.toArray(predicates);
            return criteriaBuilder.and(predicates);
        };

        // 指定排序和分页
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        PageRequest pageRequest = PageRequest.of(page < 0 ? 0 : page, pageSize, sort);
        Page<Actor> actorPage = specificationRepository.findAll(specification, pageRequest);
        log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, actorPage.getTotalElements(), actorPage.getTotalPages());
        List<Actor> actorListBySpecification = actorPage.getContent();
        return actorListBySpecification;
    }
}

判断条件值是否存在,动态追加条件。 注意指定的字段是实体类中的属性名而非表中的字段名。

1.3、测试
代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class SpecificationTest {
    @Autowired
    private SpecificationService specificationService;

    @Test
    public void testSpecification() {
        List<Actor> actorList = specificationService.findBySpecification(1L, null, 0, 10);
        log.info(JSONUtil.toJsonPrettyStr(actorList));
    }
}

多次修改查询条件测试,可以看出查询条件是根据实际情况动态追加的。

2、ExampleMatcher进行查询

2.1、创建Repository
代码语言:javascript
复制
public interface ExampleMatcherRepository extends JpaRepository<Actor, Long> {
    
}
2.2、Service
代码语言:javascript
复制
@Service
@Transactional
@Slf4j
public class ExampleMatcherServiceImpl implements ExampleMatcherService {
    @Autowired
    private ExampleMatcherRepository exampleMatcherRepository;

    @Override
    public List<Actor> findByExampleMatcher(String actorEmailPre, String actorNamePre, Integer page, Integer pageSize) {
        Actor actor = new Actor();
        actor.setActorEmail(actorEmailPre);
        actor.setActorName(actorNamePre);
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("actorEmail", ExampleMatcher.GenericPropertyMatchers.startsWith())
                .withMatcher("actorName", ExampleMatcher.GenericPropertyMatchers.startsWith())
                .withIgnoreCase() // 忽略大小写,MYSQL模糊查询默认也会忽略大小写
                .withIgnoreNullValues() // 忽略null值
                // 默认会匹配所有字段作为查询条件,所以需要设置忽略哪些字段不作为条件匹配,即这些字段可以任意值
                .withIgnorePaths("actorAge", "createTime");

        Example<Actor> actorExample = Example.of(actor, matcher);

        // 指定排序和分页
        Sort sort = new Sort(Sort.Direction.ASC, "actorAge");
        PageRequest pageRequest = PageRequest.of(page < 0 ? 0 : page, pageSize, sort);
        Page<Actor> actorPage = exampleMatcherRepository.findAll(actorExample, pageRequest);
        log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, actorPage.getTotalElements(), actorPage.getTotalPages());
        List<Actor> actorListByExampleMatcher = actorPage.getContent();
        return actorListByExampleMatcher;
    }
}

模糊查询匹配字符串。

2.3、测试
代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class ExampleMatcherTest {
    @Autowired
    private ExampleMatcherService exampleMatcherService;

    @Test
    public void testExampleMatcher() {
        List<Actor> actorList = exampleMatcherService.findByExampleMatcher("EMAIL", "name", 0, 10);
        log.info(JSONUtil.toJsonPrettyStr(actorList));
    }
}

代码地址

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Specifications进行查询
    • 1.1、创建Repository
      • 1.2、Service
        • 1.3、测试
        • 2、ExampleMatcher进行查询
          • 2.1、创建Repository
            • 2.2、Service
              • 2.3、测试
              • 代码地址
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档