QueryDsl与SpringDataJPA实现分页级联查询出现重复数据

QueryDsl与SpringDataJPA实现分页级联查询出现重复数据

1.需求

项目中资源交换任务实现多表级联查询。
两表一对多关系,需要多字段查询。

2.界面

在这里插入图片描述

3.业务代码

QueryDsl提供了对JPA,SQL,Collection,MongoDB等不同类型查询的实现。
这里讲解和SpringDataJPA集成实现多表分页级联查询。

@Override
    public Page<DirExchangeCfgDetailDto> searchDetailByPage(Pageable pageable, MultiValueMap<String, String> parameters) {
        if (pageable.getSort().isUnsorted()) {
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), QSort.by(qCfgEntity.createDate.desc(),qCfgDetailEntity.id.desc()));
        }
        Page<Tuple> tuplePage = repository.findAll(null, pageable, jpqlQuery -> jpqlQuery.from(qCfgEntity).innerJoin(qCfgDetailEntity)
                .on(qCfgDetailEntity.configId.eq(qCfgEntity.id)).where(builderConditions(parameters)), qCfgDetailEntity,qCfgEntity);

        return tuplePage.map(tuple -> {
            DirExchangeCfgDetailDto cfgDetailDto =  dtoMapper.map(tuple.get(qCfgDetailEntity), DirExchangeCfgDetailDto.class);
            // 判断是否为默认任务
            if (DEFAULT_EXCHANGE_CFG_CODE.equalsIgnoreCase(tuple.get(qCfgEntity).getCfgCode())) {
                cfgDetailDto.setIsDefault(true);
            }else {
                cfgDetailDto.setIsDefault(false);
            }
            cfgDetailDto.setCfgName(tuple.get(qCfgEntity).getCfgName());
            cfgDetailDto.setFlowDirection(tuple.get(qCfgEntity).getFlowDirection());
            cfgDetailDto.setChangeType(tuple.get(qCfgEntity).getChangeType());
            cfgDetailDto.setCronStr(tuple.get(qCfgEntity).getCronStr());
            return cfgDetailDto;
        });
    }
private BooleanBuilder builderConditions(MultiValueMap<String, String> parameters) {
        final String resourceName = parameters.getFirst("resourceName");
        final String availableStatus = parameters.getFirst("availableStatus");
        final String flowDirection = parameters.getFirst("flowDirection");
        final String changeType = parameters.getFirst("changeType");
        BooleanBuilder builder = new BooleanBuilder();
        if (StringUtils.isNotEmpty(resourceName)) {
            builder.and(qCfgDetailEntity.resourceName.eq(resourceName));
        }
        if (StringUtils.isNotEmpty(availableStatus)) {
            builder.and(qCfgDetailEntity.availableStatus.eq(availableStatus));
        }
        if (StringUtils.isNotEmpty(flowDirection)) {
            builder.and(qCfgEntity.flowDirection.eq(flowDirection));
        }
        if (StringUtils.isNotEmpty(changeType)) {
            builder.and(qCfgEntity.changeType.eq(changeType));
        }
        return builder;
    }

主要调用JPQLQuery的方法,将结果存放到一个Tuple的多元组中.相比原生sql,简单清晰了很多。
多表投影查询示例:
在这里插入图片描述
把集合封装成Page返回。

4.重复数据问题

当设置交换任务为主表(一对多表中的多项表)进行多表映射查询时,会出现重复的返回数据。
在这里插入图片描述
发现问题出现在QueryDsl执行编译好的sql语句,看到sql语句关联变成了cross join交叉查询,无论是left join还是其他是同样情况。
在这里插入图片描述
解决方法需要设交换方案表(一对多表中的单项对应表)为主表,交换位置。
在这里插入图片描述
编译sql语句正常。
在这里插入图片描述

5.总结

当遇到复杂、投影、动态查询时我们可以考虑使用QueryDSL做开发。以上方案可以解决大多数持久层开发问题。在使用SpringDataJPA和QueryDSL实现多表关联级联查询时,注意将一对多单项关联表设为主表进行查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值