Spring Data JPA实现复杂的动态查询

一、JPA介绍

JPA的动态查询通过Specification接口实现,用于当jpa的一些基本CRUD操作的扩展,即spring jpa的复杂查询接口。

1.1、关于Specification用于表单实现多条件动态查询

通过看Specification的源码,能看到可用的方法就一个toPredicate;



	/**
	 * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
	 * {@link Root} and {@link CriteriaQuery}.
	 *
	 * @param root must not be {@literal null}.
	 * @param query must not be {@literal null}.
	 * @param criteriaBuilder must not be {@literal null}.
	 * @return a {@link Predicate}, may be {@literal null}.
	 */
	@Nullable
	Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);

正好项目中,有mybatis转为JPA了,需要写一个多查询条件的DAO方法。以下为DAO层代码示例

Page<GatewayAccess> findAll(Specification<GatewayAccess> specification,Pageable pageable);
default  Page<GatewayAccess> findByAppIdAndApiIdAndStatusAndJnlNo(String beginTime,String endTime,String appId,String apiId,String status,String jnlNo,Pageable pageable) {

        Specification<GatewayAccess> specification = new Specification<GatewayAccess>() {
            @SneakyThrows
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //增加筛选条件
                Predicate predicate = cb.conjunction();
                //大于等于
                predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("tradeTime"), formatter.get().parse(beginTime)));
                //小于
                predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("tradeTime"),formatter.get().parse(endTime)));
                if (StringUtils.isNotBlank(appId)) {
                    predicate.getExpressions().add(cb.equal(root.get("appId"),appId));
                }
                if (StringUtils.isNotBlank(apiId)) {
                    predicate.getExpressions().add(cb.equal(root.get("apiId"),apiId));
                }
                if (StringUtils.isNotBlank(status)) {
                    predicate.getExpressions().add(cb.equal(root.get("status"),status));
                }
                if (StringUtils.isNotBlank(jnlNo)) {
                    predicate.getExpressions().add(cb.equal(root.get("jnlNo"),jnlNo));
                }
                return predicate;
            }
        };
        return findAll(specification,pageable);
    }

 

二、Specification除了能使实现单表查询,还能实现多表关联查询,分组查询、排序等

多表查询

**
 * 构建查询条件 三张表内联查询实例
 *
 * @param categoryId 分类id
 * @param name       商品名称
 * @param shopId     店铺id
 * @return 查询条件
 */
public Specification<ProductGroup> buildProductGroupSpec(Integer shopId, String name, Integer categoryId, Integer shopKindId, Boolean health) {
    return (root, query, cb) -> {
        Join<ProductGroup, Shop> shopJoin = root.join("shop", JoinType.INNER);
        Join<Shop, ShopDatum> shopDatumJoin = shopJoin.join("shopDatum", JoinType.INNER);
        Join<Shop, ShopConfig> shopConfigJoin = shopJoin.join("shopConfig", JoinType.INNER);
        List<Predicate> predicates = Lists.newArrayList();
        if (shopId != null) {
            predicates.add(cb.equal(root.get("shop"), shopId));
        }
        if (StringUtils.isNotEmpty(name)) {
            predicates.add(cb.like(root.get("name"), "%" + name.trim() + "%"));
        }
        if (categoryId != null) {
            predicates.add(cb.equal(root.get("category"), categoryId));
        }
        if (shopKindId != null && shopKindId != 0) {
            predicates.add(cb.like(root.get("shopKindIds"), "," + shopKindId + ","));
        }
        predicates.add(cb.equal(root.get("auditState"), AUDIT_STATE_YES.getKey()));
        predicates.add(cb.equal(root.get("offline"), Boolean.FALSE));
        predicates.add(cb.greaterThanOrEqualTo(shopDatumJoin.get("openShopExpire"), new Date()));
        predicates.add(cb.equal(shopConfigJoin.get("openShop"), Boolean.TRUE));
        Predicate p1 = cb.equal(root.get("health"), Boolean.FALSE);
        Predicate p2 = cb.equal(root.get("health"), Boolean.TRUE);
        Predicate p3 = cb.greaterThanOrEqualTo(shopDatumJoin.get("openHealthShopExpire"), new Date());
        if (health == null) {
            predicates.add(cb.or(p1, cb.and(p2, p3)));
        }
        if (health != null) {
            if (health) {
                predicates.add(cb.and(p2, p3));
            } else {
                predicates.add(cb.and(p1));
            }
        }
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    };
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值