【Springboot JPA】多种条件查询分页

本文探讨了如何通过JPA分页查询和自定义SQL实现产品表的分页,包括按创建时间、名称模糊搜索、标签筛选,并详细展示了如何将标签过滤转换为SQL IN条件。Service层通过`ProductService`实现复杂条件的查询,包括`ProductRepository`的整合和自定义RowMapper的运用。
摘要由CSDN通过智能技术生成

数据库表-对应Entity

产品表 my_products

product_nameproduct_id(主键)create_time(上架时间)product_info
电脑12021-08-27 17:28:57.076(bytes)
手机22021-08-27 17:28:57.076(bytes)
导管32021-08-27 17:28:57.076(bytes)

关联表 my_tag_relation

tag_idid(主键)product_id
111
223
132

标签表 my_tag

tag_id(主键)tag_nametype
1电子产品1
2其他产品1
3食品1

需求

产品表分页;
可以按createTime时间过滤筛选
可以按商品名称productName模糊查询筛选
可以按商品名称productId模糊查询筛选
可以按标签名称筛选

分页查询实现

按标签过滤,原本是表关联查询后过滤,这个jpa分页看起来无法联表写条件,我没有找到写法;
那就把这个转换成简单的条件。在tagRelationRepository中查询出符合标签条件的distinct(product_id).

														
    public List<String> findProductIdsByTagNames(List<String> tagNames) {
    											//要查询的标签名称
        Set<String> tagSet = new HashSet<>();
        tagSet.addAll(tagNames);

        String inFilterValues = createInFilterValues(tagSet);

        String sql = "SELECT distinct(r.product_id) from my_tag_relation r LEFT JOIN my_tag t on r.tag_id=t.id where t.tag in (" + inFilterValues + ");";
        List<String> productIds= jdbcTemplate.queryForList(sql, String.class);
        return productIds;
    }

	//拼接sql  'tag1','tag2'
    public String createInFilterValues(Set<String> tagSet) {
        StringBuilder sb = new StringBuilder();
        for (String tag : tagSet) {
            sb.append("'").append(tag).append("',");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

再将这个product_ids给jpa分页的in条件。
需Service层实现

@Service
public class ProductService{
	@Autowired
	ProductRepository productRepository;

	/**
     * 分页查询、按多种条件过滤
     */
    public Map<String, Object> pageByParams(ProductListParams params) {
    	Map<String, Object> res = new HashMap<>();
        String startTime = params.getStartTime();
        String endTime = params.getEndTime();
        Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "createTime"));
        PageRequest pageRequest = new PageRequest(params.getPage() - 1, params.getLimit(), sort);
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //增加筛选条件 productInfo is not null
                Predicate predicate = cb.conjunction();
                predicate.getExpressions().add(cb.isNotNull(root.get("productInfo").as(byte[].class)));
                //标签过滤 转换为productId in ()
                if (params.getTagNames() != null && params.getProductIds() != null) {
                    predicate.getExpressions().add(root.get("productId").as(String.class).in(params.getProductIds()));
                }
                //名称过滤
                if (params.getProductIdFilter() != null && params.getProductIdFilter().length() > 0) {
                    predicate.getExpressions().add(cb.like(root.get("productId").as(String.class), "%" + params.getProductIdFilter() + "%"));
                }
                if (params.getProductNameFilter() != null && params.getProductNameFilter().length() > 0) {
                    predicate.getExpressions().add(cb.like(root.get("productName").as(String.class), "%" + params.getProductNameFilter() + "%"));
                }
                //起始日期
                if (startTime != null && !startTime.trim().equals("")) {
                    predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("createTime").as(String.class), startTime));
                }
                //结束日期
                if (endTime != null && !endTime.trim().equals("")) {
                    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("createTime").as(String.class), endTime));
                }
                return predicate;
            }
        };
		Page<RasterLayerEntity> page = rasterLayerRepository.findAll(specification, pageRequest);
        Stream<RasterLayerEntity> rasterLayerEntityStream = page.get();
        List<RasterLayerEntity> entities = rasterLayerEntityStream.collect(Collectors.toList());
        setBatchEntityTagNames(entities);
        res.put("totalElements", page.getTotalElements());
        res.put("totalPages", page.getTotalPages());
        res.put("values", entities);
        return res;
    }
}

自己写分页(虽然麻烦,但是也能很好解决问题,可控性强)

使用jdbcTemplate执行sql

条件自己写sql,联表条件使用联表查询
分页使用offset limit.有自增主键则使用主键,id > 80 limit 10,速度更快

Entity映射需要自己实现,写一个RowMapper

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值