使用Spring Data JPA进行谓词查询和分页的数据查询

4
我曾经不幸地在Java领域工作过一段时间,而我来自于.net世界。撇开抱怨,我只是想实现一个能够处理预测使用并且必须有分页功能的存储库。我找不到一个好的方法来实现这个功能。
// IContactRepository.java
public interface IContactRepository extends Repository<Contact,Long> {

}
// Application.java
contactRepo.findAll(predicate, new PageRequest(0,10));

我希望能够通过搜索词来查找包含联系人姓名或联系电话号码的联系人,并获取前10个匹配项。

在.NET世界中,如果我不使用ORM,我会使用SQL Server的强大TSQL来获取我想要的结果,但现在我却被Oracle困住了。否则,我会使用一些ORM并将一个lambda作为谓词传递给查询函数。


你想动态添加谓词吗? - cgon
目前谓词需要足够动态,以便我可以在联系人姓名或联系人号码上执行类似的查询并返回分页结果。 - Perpetualcoder
因为我认为从C#转向Java是一种不幸,所以我会给它点踩? - Perpetualcoder
3个回答

3

在我的配置中,我还使用了JPA和Spring。(针对静态谓词。如果您想动态添加谓词(搜索条件),请告诉我。)

// IContactRepository.java
public interface IContactRepository extends CrudRepository<Contact,Long>, PagingAndSortingRepository<Contact, Long>  {
    List<Contact> findByContactNameLikeAndContactPhoneLike(String name, String phone, Pageable pageable)
}

我尝试使用CrudRepo和Pageable,效果很好。关于lambda表达式你说得对 :)
在我的配置中,你的实现看起来像这样:
IContactRepository contactRepo = context.getBean(IContactRepository.class);
List<Contacts> results = contactRepo.findByContactNameLikeAndContactPhoneLike("%CA%","%090%" , new PageRequest(1, 20));

请查看“1.2.2 定义查询方法”下的“查询创建”部分,相关内容可以在以下链接中找到:http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

这对我想做的事情很有帮助。感谢您对我的新手问题没有进行评判。 - Perpetualcoder

2
这是我的实现,或许可以帮助你:

这是最初的回答:

@Override
public Page<Advert> findActiveAdverts(String searchValue, String availability, Long branchId, Long categoryId, Pageable pageable) {
    Page<Advert> adverts = advertRepository.findAll(new Specification<Advert>() {
        @Override
        public javax.persistence.criteria.Predicate toPredicate(Root<Advert> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            List<Predicate> predicates = new ArrayList<>();

            predicates.add(cb.equal(root.get(Advert_.ACTIVE), true));

            if (!StringUtils.isEmpty(searchValue)) {
                predicates.add(cb.or(
                        cb.like(root.get(Advert_.TITLE), "%" + searchValue + "%"),
                        cb.like(root.get(Advert_.EXPLANATION), "%" + searchValue + "%"))
                );
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        }
    }, pageable);
    return adverts;
}

2
我猜你在查看Predicate是因为你想执行任意复杂的查询。然而,没有findAll(Predicate, Pageable)方法。我建议你查看SpecificationJpaSpecificationExecutor。你的代码应该像这样:
public interface IContactRepository extends JpaRepository<Contact,Long>, JpaSpecificationExecutor<Contact> {

}

那么你将可以访问方法 findAll(Specification, Pageable)。根据您的要求,Specification 是一个函数式接口,因此您可以使用lambda轻松地传入实现。
有关更多详细信息,请查看文档的第2.5节。
这里是SpecificationJavadoc,这里是JpaSpecificationExecutorJavadoc
另外,如果您必须忍受Java的痛苦,您应该放弃在IContactRepository中的I。通常Java代码会放弃.NET的这种做法。

1
我在这里找到了我尝试使用的findAll变体:http://docs.spring.io/spring-data/commons/docs/1.7.2.RELEASE/api/org/springframework/data/querydsl/QueryDslPredicateExecutor.html#findAll(com.mysema.query.types.Predicate, org.springframework.data.domain.Pageable)。 - Perpetualcoder
我没有意识到你在看QueryDSL变体!我的错! - geoand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接