【问题标题】:How to implement Spring Data Jpa Dynamic Query and Joint inquirySpring Data Jpa动态查询和联合查询如何实现
【发布时间】:2015-10-31 03:26:08
【问题描述】:

当前项目我使用了Spring data jpa和spring boot,大多数时候我发现它很容易满足这个要求,我发现很难处理。 那就是我有买家实体和供应商实体以及中间实体(BuyerSupplier),如果我想通过电话或姓名或两者或全部搜索买家,我必须提供许多方法,如下所示:

if(phone!=null&&name!=null)
    List<Buyer> findByPhoneAndName(phone,name)
else if(phone!=null)
    List<Buyer> findByPhone(phone)
else if(name!=null)
    List<Buyer> findByName(name)
else
    List<Buyer> findAll()

显然,上面的代码很糟糕。实际上,我的业务逻辑更复杂,同时我想搜索属于特殊供应商的买家,也许是特殊身份的买家。对应的sql如下:

select b.* from buyer b, buyer_supplier bs
where b.id = bs.buyer_id
and bs.supplier_id = 1
and bs.stauts = 'Activated'
and b.name like '%foo%'
and b.phone like '%123%'

我还想构建动态sql,如下所示:

select b.* from buyer b, buyer_supplier bs
where b.id = bs.buyer_id
if(name != null)
    and b.name like '%foo%'
if(phone!=null)
    and b.phone like '%123%'
if(supplierId>0)
    and b.supplier_id = 1
if(status!=null)
    and bs.stauts = 'Activated'

谁能给我一些代码示例或文档可以教我如何实现我的上述目标?

【问题讨论】:

    标签: spring-data-jpa


    【解决方案1】:

    IMO,您仍然需要编写像if(phone!=null&amp;&amp;name!=null) 这样的代码。但是您可以对代码进行转义,并编写一次。 首先,你应该知道Specification&lt;T&gt;很好地支持动态查询。下面贴上我的代码。

    Specification<Goods> spec = new Specification<Goods>() {
        @Override
        public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
             Predicate predicate = cb.conjunction();
                    if (goodsSearch.getGoodsClassId() != -1) {
                        predicate = cb.and(predicate, cb.equal(root.get("goodsClassId"), goodsSearch.getGoodsClassId()));
                    }
    
                    return query.where(predicate).getRestriction();
                }
            };
    return goodsDao.findAll(spec, pageable);
    

    好的,你可以用lambda代替匿名类。然后你可以把Specification&lt;T&gt;转义,把if(phone!=null&amp;&amp;name!=null)这样的代码放进去。 示例代码:

    public Specification<T> term(String fieldName, Operator operator, Object value) {
            return new Specification<T>() {
                @Override
                public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder builder) {
                    if (value == null) {
                        return null;
                    }
                    Path expression = null;
                    // if a.b, then use join
                    if (fieldName.contains(".")) {
                        String[] names = StringUtils.split(fieldName, ".");
                        expression = root.get(names[0]);
                        for (int i = 1; i < names.length; i++) {
                            expression = expression.get(names[i]);
                        }
                    } else {
                        expression = root.get(fieldName);
                    }
                    // the different operation
                    switch (operator) {
                        case EQ:
                            return builder.equal(expression, value);
                        case NE:
                            return builder.notEqual(expression, value);
                        case LT:
                            return builder.lessThan(expression, (Comparable) value);
                        case GT:
                            return builder.greaterThan(expression, (Comparable) value);
                        case LIKE:
                            return builder.like((Expression<String>) expression, "%" + value + "%");
                        case LTE:
                            return builder.lessThanOrEqualTo(expression, (Comparable) value);
                        case GTE:
                            return builder.greaterThanOrEqualTo(expression, (Comparable) value);
                        case BT:
                            List<Object> paramList = (List<Object>) value;
                            if (paramList.size() == 2) {
                                return builder.between(expression, (Comparable) paramList.get(0), (Comparable) paramList.get(1));
                            }
                        case IN:
                            return builder.in(expression).value(value);
                        default:
                            return null;
                    }
                }
            };
        }
    

    我没有在里面写示例代码if(phone!=null&amp;&amp;name!=null)

    【讨论】:

      猜你喜欢
      • 2015-01-27
      • 2019-02-20
      • 1970-01-01
      • 2018-07-25
      • 2013-12-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      相关资源
      最近更新 更多