使用Spring-boot扩展CrudRepository中的动态条件进行查询

时间:2016-07-25 11:34:58

标签: java spring spring-boot

我有一个spring-boot应用程序,我希望有一个动态查询条件,即我想创建一个可以接收以下可选参数的方法:Age和Name。我的问题是,这些参数是可选的,这意味着它们有时可能是NULL,我想动态构建我的查询,例如,如果参数不为null或为空,我将它们作为标准放在我的查询中,否则我不# 39;吨

我为此问题找到的解决方案基本上是为我的存储库(UserRepositoryCustomImpl)创建自定义实现,并自己构建查询。然而,我想知道是否没有"面向弹簧的解决方案",就像一些注释,或类似的东西,我可以说,"嘿,使用这个地图,动态地构建这个查询"

1 个答案:

答案 0 :(得分:0)

我觉得我的情况也是如此:我的HTML表单有N个过滤器,但是我希望它们仅在选择或更改时才适用于搜索。一旦你根据它的相应选择,输入等对表单进行建模,如果没有选择任何这些字段或具有默认值,只需要忽略但仍然使用Spring的方便和易用性Repository(在我的案例中是JpaRespository)。

通过我的小Spring视角,我尝试使用Specification方法(IMO比实现自定义存储库更好)。它运作完美,但不知道这是否是最佳方式。

以下是官方的Spring示例https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

这里有一个简单的个人示例(并且可能打破一些最佳编码实践,目的是可以理解):

MyObjectRepository.java

    public interface MyObjectRepository extends JpaRepository<MyObject, Long>, JpaSpecificationExecutor<MyObject> { }           

MyObjectServiceImpl.java

@Service("MyObjectService")
public class MyObjectServiceImpl implements MyObjectService {

@Autowired
MyObjectRepository myObjectRespository;

@Override
public Page<MyObject> getAllMyObjectByFields(int pageIndex, FormMyObject formMyObject) {
    Specification<MyObject> spec = new Specification<MyObject>() {
          @Override
          public Predicate toPredicate(Root<MyObject> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
            if (formMyObject == null) {
              throw new IllegalStateException("At least one parameter should be provided to construct complex query");
            }
            List<Predicate> predicates = new ArrayList<Predicate>();
                // only if the content is present add a criteria to the search, you decide/know if will be null, or empty...
                if (formMyObject.getYourField() != null && formMyObject.getYourField().length() > 0) {
                   predicates.add(
                           builder.and(builder.equal(root.get("field"), formMyObject.getYourField())));
                }

                // add as many criteria as you want/need
                if(){
                   predicates.add( ... );
                }


                Predicate[] predicatesArray = new Predicate[predicates.size()];
            return builder.and(predicates.toArray(predicatesArray));
          }
    };

    PageRequest page = new PageRequest(pageIndex, formMyObject.getMaxResult());     
    // using the built in findAll method from Repository with dynamic custom filters 
    return myObjectRespository.findAll(spec, page);