栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

支持多数据源竟然这么简单(SpringJPA从使用原生SQL转为QueryDSL实现)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

支持多数据源竟然这么简单(SpringJPA从使用原生SQL转为QueryDSL实现)

QueryDSL使用

往期文章链接

[Spring data jpa] 使用EntityManager 原生sql使用(详细)

前文提要:

公司项目使用的数据源框架为Spring Data JPA,在实现复杂功能时,我选择了用原生SQL语句来实现.最近有客户要求项目能够支持SQL Server数据库,需要把项目中的所有的原生SQL语句改为QueryDSL,复杂的SQL用QueryDSL来实现相当麻烦,下面记录一下转换的过程.

之前使用原生SQL语句的实现代码(细节请看往期文章链接):
	@PersistenceContext
	private EntityManager entityManager;

	@Override
    @SuppressWarnings("unchecked")
    public List pageAttendanceStatisticse(Integer siteId, Date stateTime, Date endTime, String statue, String personName, Pageable pageable, Integer groupId) {

        StringBuilder dataSql = new StringBuilder(
                "select a.id as attendanceId," +
                        "p.person_no as personNo," +
                        "p.name as personName," +
                        "eg.name as groupName," +
                        "eg.id as groupId,"
                        + "COUNT(CASE when floor(status/10) = 1 then 1 else NULL end) as absences,"
                        + "COUNT(CASE when floor(status/10) = 2 then 1 else NULL end) as lateNumber,"
                        + "COUNT(CASE when floor(status/10) = 3 then 1 else NULL end) as leaveEarly,"
                        + "COUNT(CASE when floor(status/10) = 4 then 1 else NULL end) as normalDays,"
                        + "COUNT(CASE when status_b = 1 then 1 else NULL end) as bAbsences,"
                        + "COUNT(CASE when status_b = 2 then 1 else NULL end) as bLateNumber,"
                        + "COUNT(CASE when status_b = 3 then 1 else NULL end) as bLeaveEarly,"
                        + "COUNT(CASE when status_b = 4 then 1 else NULL end) as bNormalDays,"
                        + "COUNT(CASE when status_c = 1 then 1 else NULL end) as cAbsences,"
                        + "COUNT(CASE when status_c = 2 then 1 else NULL end) as cLateNumber,"
                        + "COUNT(CASE when status_c = 3 then 1 else NULL end) as cLeaveEarly,"
                        + "COUNT(CASE when status_c = 4 then 1 else NULL end) as cNormalDays,"
                        + "COUNT(CASE when status_d = 1 then 1 else NULL end) as dAbsences,"
                        + "COUNT(CASE when status_d = 2 then 1 else NULL end) as dLateNumber,"
                        + "COUNT(CASE when status_d = 3 then 1 else NULL end) as dLeaveEarly,"
                        + "COUNT(CASE when status_d = 4 then 1 else NULL end) as dNormalDays,"
                        + "COUNT(CASE when status%10 = 5 then 1 else NULL end) as workOvertime,"
                        + "COUNT(CASE when status%10 = 6 then 1 else NULL end) as festivalOvertime,"
                        + "COUNT(CASE when status%10 = 7 then 1 else NULL end) as holidayOvertime "
                        + "from tdx_attendance_record a left join tdx_employee e on a.employee_id = e.id left join tdx_person p on e.person_id = p.id left join tdx_employee_group eg on e.group_id = eg.id");

        //拼接where条件
        StringBuilder whereSql = new StringBuilder(" WHERe e.attendance_rule_id is not null and a.deleted_flag = 0");
        if (null != siteId) {
            whereSql.append(" and a.site_id = :siteId");
        }
        if (null != stateTime && null != endTime) {
            whereSql.append(" and a.attendance_date BETWEEN :stateTime and :endTime");
        }
        if (StringUtils.isNotEmpty(personName)) {
            whereSql.append(" and p.name like concat('%',:personName,'%')");
        }
        if (null != groupId && groupId != 0) {
            whereSql.append(" and eg.id = :groupId");
        }

        StringBuilder groupBySql = new StringBuilder(" GROUP BY a.employee_id");
        dataSql.append(whereSql).append(groupBySql);

        if (null != pageable) {
            StringBuilder limitSql = new StringBuilder(" limit :offset,:pageSize");
            dataSql.append(limitSql);
        }

        Query dataQuery = entityManager.createNativeQuery(dataSql.toString());
        dataQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(AttendanceStatisticsVo.class));

        //设置参数
        if (null != siteId) {
            dataQuery.setParameter("siteId", siteId);
        }
        if (null != stateTime && null != endTime) {
            dataQuery.setParameter("stateTime", stateTime);
            dataQuery.setParameter("endTime", endTime);
        }
        if (StringUtils.isNotEmpty(personName)) {
            dataQuery.setParameter("personName", personName);
        }
        if (null != groupId && groupId != 0) {
            dataQuery.setParameter("groupId", groupId);
        }
        if (null != pageable) {
            Long offset = pageable.getOffset();
            Integer pageSize = pageable.getPageSize();
            dataQuery.setParameter("offset", offset);
            dataQuery.setParameter("pageSize", pageSize);
        }
        List resultList = dataQuery.getResultList();
        return dataQuery.getResultList();
    }
使用 QueryDSL实现代码,仅供参考:
  1. maven依赖
	  
      
            com.querydsl
            querydsl-jpa
        
        
            com.querydsl
            querydsl-apt
        
        
            com.querydsl
            querydsl-sql
        
        
            org.hibernate
            hibernate-ehcache
        
  1. 替换SUM,CASE THEN

举例: 替换下面的SQL

SUM(CASE when floor(status/10) = 1 then 1 else 1 end) as absences
  • 创建CaseBuilder
Numberexpression absences = new CaseBuilder().when(qAttendanceRecord.status.divide(10).floor().eq(1)).then(1).otherwise(0);
  • 创建BooleanBuilder
//用SUM函数来计算CASE WHEN后的字段总数
BooleanBuilder havingBooleanBuilder = new BooleanBuilder();
havingBooleanBuilder.and(absences.sum().gt(0));
  1. 替换where语句
  • 举例
if (StringUtils.isNotEmpty(personName)) {
     whereSql.append(" and p.name like concat('%',:personName,'%')");
}
  • 更改后的代码
BooleanBuilder booleanBuilder = new BooleanBuilder();
if (StringUtils.isNotEmpty(personName)) {
     booleanBuilder.and(qAttendanceRecord.employee.person.name.like("%" + personName + "%"));
}
  1. 整合
  • 查询完整代码
public List pageAttendanceStatistics(Integer siteId, Date stateTime, Date endTime, String statue, String personName,
                                                                 Pageable pageable, Integer groupId) {
        QAttendanceRecord qAttendanceRecord = QAttendanceRecord.attendanceRecord;
        //where语句
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder
                .and(qAttendanceRecord.employee.attendanceRuleId.isNotNull())
                .and(qAttendanceRecord.hasDeleted.eq(false));
        if (null != siteId) {
            booleanBuilder.and(qAttendanceRecord.siteId.eq(siteId));
        }
        if (null != stateTime && null != endTime) {
            booleanBuilder.and(qAttendanceRecord.attendanceDate.between(stateTime, endTime));
        }
        if (StringUtils.isNotEmpty(personName)) {
            booleanBuilder.and(qAttendanceRecord.employee.person.name.like("%" + personName + "%"));
        }
        if (null != groupId && groupId != 0) {
            booleanBuilder.and(qAttendanceRecord.employee.employeeGroup.id.eq(groupId));
        }
        //查询带函数字段
        Numberexpression absences = new CaseBuilder().when(qAttendanceRecord.status.divide(10).floor().eq(1)).then(1).otherwise(0);
        Numberexpression lateNumber = new CaseBuilder().when(qAttendanceRecord.status.divide(10).floor().eq(2)).then(1).otherwise(0);
        Numberexpression leaveEarly = new CaseBuilder().when(qAttendanceRecord.status.divide(10).floor().eq(3)).then(1).otherwise(0);
        Numberexpression normalDays = new CaseBuilder().when(qAttendanceRecord.status.divide(10).floor().eq(4)).then(1).otherwise(0);
        Numberexpression bAbsences = new CaseBuilder().when(qAttendanceRecord.statusB.eq(1)).then(1).otherwise(0);
        Numberexpression bLateNumber = new CaseBuilder().when(qAttendanceRecord.statusB.eq(2)).then(1).otherwise(0);
        Numberexpression bLeaveEarly = new CaseBuilder().when(qAttendanceRecord.statusB.eq(3)).then(1).otherwise(0);
        Numberexpression bNormalDays = new CaseBuilder().when(qAttendanceRecord.statusB.eq(4)).then(1).otherwise(0);
        Numberexpression cAbsences = new CaseBuilder().when(qAttendanceRecord.statusC.eq(1)).then(1).otherwise(0);
        Numberexpression cLateNumber = new CaseBuilder().when(qAttendanceRecord.statusC.eq(2)).then(1).otherwise(0);
        Numberexpression cLeaveEarly = new CaseBuilder().when(qAttendanceRecord.statusC.eq(3)).then(1).otherwise(0);
        Numberexpression cNormalDays = new CaseBuilder().when(qAttendanceRecord.statusC.eq(4)).then(1).otherwise(0);
        Numberexpression dAbsences = new CaseBuilder().when(qAttendanceRecord.statusD.eq(1)).then(1).otherwise(0);
        Numberexpression dLateNumber = new CaseBuilder().when(qAttendanceRecord.statusD.eq(2)).then(1).otherwise(0);
        Numberexpression dLeaveEarly = new CaseBuilder().when(qAttendanceRecord.statusD.eq(3)).then(1).otherwise(0);
        Numberexpression dNormalDays = new CaseBuilder().when(qAttendanceRecord.statusD.eq(4)).then(1).otherwise(0);
        Numberexpression workOvertime = new CaseBuilder().when(qAttendanceRecord.status.mod(10).eq(5)).then(qAttendanceRecord.overtimeHours).otherwise(0);
        Numberexpression festivalOvertime = new CaseBuilder().when(qAttendanceRecord.status.mod(10).eq(6)).then(qAttendanceRecord.overtimeHours).otherwise(0);
        Numberexpression holidayOvertime = new CaseBuilder().when(qAttendanceRecord.status.mod(10).eq(7)).then(qAttendanceRecord.overtimeHours).otherwise(0);
        Numberexpression askForLeave = new CaseBuilder().when(qAttendanceRecord.status.eq(51)).then(1).otherwise(0);
        Numberexpression businessTrip = new CaseBuilder().when(qAttendanceRecord.status.eq(52)).then(1).otherwise(0);
        //having语句
        BooleanBuilder havingBooleanBuilder = new BooleanBuilder();
        if (StringUtils.isNotBlank(statue)) {
            switch (statue) {
                case ABSENT:
                    havingBooleanBuilder.and(
                            absences.sum().gt(0)
                                    .or(bAbsences.sum().gt(0))
                                    .or(cAbsences.sum().gt(0))
                                    .or(dAbsences.sum().gt(0)));
                    break;
                case LATE:
                    havingBooleanBuilder.and(
                            lateNumber.sum().gt(0)
                                    .or(bLateNumber.sum().gt(0))
                                    .or(cLateNumber.sum().gt(0))
                                    .or(dLateNumber.sum().gt(0)));
                    break;
                case LEAVE_EARLY:
                    havingBooleanBuilder.and(
                            leaveEarly.sum().gt(0)
                                    .or(bLeaveEarly.sum().gt(0))
                                    .or(cLeaveEarly.sum().gt(0))
                                    .or(dLeaveEarly.sum().gt(0)));
                    break;
                case FULL_ATTENDANCE:
                    havingBooleanBuilder.and(
                            normalDays.sum().gt(0)
                                    .or(bNormalDays.sum().gt(0))
                                    .or(cNormalDays.sum().gt(0))
                                    .or(dNormalDays.sum().gt(0)));
                    break;
                case WORK_OVERTIME:
                    havingBooleanBuilder.and(
                            workOvertime.sum().gt(0));
                    break;
                case OVERTIME_ON_HOLIDAYS:
                    havingBooleanBuilder.and(
                            festivalOvertime.sum().gt(0));
                    break;
                case OVERTIM_ON_PUBLIC_HOLIDAYS:
                    havingBooleanBuilder.and(
                            holidayOvertime.sum().gt(0));
                    break;
                case ASK_FOR_LEAVE:
                    havingBooleanBuilder.and(
                            askForLeave.sum().gt(0));
                    break;
                case BUSINESS_TRIP:
                    havingBooleanBuilder.and(
                            businessTrip.sum().gt(0));
                    break;
                default:
                    break;
            }
        }
        
        JPAQuery query = super.getJpaQueryFactory()
                .select(
                
                Projections.constructor(
                        AttendanceStatisticsVo.class,
                        qAttendanceRecord.employeeId.as("employeeId"),
                        absences.sum().as("absences"),
                        lateNumber.sum().as("lateNumber"),
                        leaveEarly.sum().as("leaveEarly"),
                        normalDays.sum().as("normalDays"),
                        bAbsences.sum().as("bAbsences"),
                        bLateNumber.sum().as("bLateNumber"),
                        bLeaveEarly.sum().as("bLeaveEarly"),
                        bNormalDays.sum().as("bNormalDays"),
                        cAbsences.sum().as("cAbsences"),
                        cLateNumber.sum().as("cLateNumber"),
                        cLeaveEarly.sum().as("cLeaveEarly"),
                        cNormalDays.sum().as("cNormalDays"),
                        dAbsences.sum().as("dAbsences"),
                        dLateNumber.sum().as("dLateNumber"),
                        dLeaveEarly.sum().as("dLeaveEarly"),
                        dNormalDays.sum().as("dNormalDays"),
                        workOvertime.sum().as("workOvertime"),
                        festivalOvertime.sum().as("festivalOvertime"),
                        holidayOvertime.sum().as("holidayOvertime"),
                        askForLeave.sum().as("askForLeave"),
                        businessTrip.sum().as("businessTrip")
                ))
                .from(qAttendanceRecord)
                .where(booleanBuilder)
                .groupBy(qAttendanceRecord.employeeId)
                .having(havingBooleanBuilder);
        //分页
        if (null != pageable) {
            query.offset(pageable.getOffset()).limit(pageable.getPageSize());
        }
        return query.fetch();
    }
  • VO对象
@Data
public class AttendanceStatisticsVo implements Serializable {

    private static final long serialVersionUID = -8440165638031432031L;

    
    private Integer employeeId;
    
    private Integer attendanceId;
    
    private String personNo;
    
    private String personName;
    
    private String groupName;
    
    private Integer groupId;
    
    private Integer absences;
    
    private Integer lateNumber;
    
    private Integer leaveEarly;
    
    private Integer normalDays;
    
    private Integer bAbsences;
    
    private Integer bLateNumber;
    
    private Integer bLeaveEarly;
    
    private Integer bNormalDays;
    
    private Integer cAbsences;
    
    private Integer cLateNumber;
    
    private Integer cLeaveEarly;
    
    private Integer cNormalDays;
    
    private Integer dAbsences;
    
    private Integer dLateNumber;
    
    private Integer dLeaveEarly;
    
    private Integer dNormalDays;
    
    private Integer workOvertime;
    
    private Integer festivalOvertime;
    
    private Integer holidayOvertime;
    
    private Integer askForLeave;
    
    private Integer businessTrip;

    public AttendanceStatisticsVo() {

    }

    public AttendanceStatisticsVo(Integer attendanceId, String personNo, String personName, String groupName) {
        this.attendanceId = attendanceId;
        this.personNo = personNo;
        this.personName = personName;
        this.groupName = groupName;
    }

    public AttendanceStatisticsVo(Integer attendanceId, String personNo, String personName, String groupName, Integer groupId) {
        this.attendanceId = attendanceId;
        this.personNo = personNo;
        this.personName = personName;
        this.groupName = groupName;
        this.groupId = groupId;
    }

    public AttendanceStatisticsVo(Integer employeeId, Integer absences, Integer lateNumber,
            Integer leaveEarly, Integer normalDays, Integer bAbsences, Integer bLateNumber, Integer bLeaveEarly, Integer bNormalDays, Integer cAbsences, Integer cLateNumber,
            Integer cLeaveEarly, Integer cNormalDays, Integer dAbsences, Integer dLateNumber, Integer dLeaveEarly, Integer dNormalDays, Integer workOvertime, Integer festivalOvertime,
            Integer holidayOvertime, Integer askForLeave, Integer businessTrip) {
        this.employeeId = employeeId;
        this.absences = absences;
        this.lateNumber = lateNumber;
        this.leaveEarly = leaveEarly;
        this.normalDays = normalDays;
        this.bAbsences = bAbsences;
        this.bLateNumber = bLateNumber;
        this.bLeaveEarly = bLeaveEarly;
        this.bNormalDays = bNormalDays;
        this.cAbsences = cAbsences;
        this.cLateNumber = cLateNumber;
        this.cLeaveEarly = cLeaveEarly;
        this.cNormalDays = cNormalDays;
        this.dAbsences = dAbsences;
        this.dLateNumber = dLateNumber;
        this.dLeaveEarly = dLeaveEarly;
        this.dNormalDays = dNormalDays;
        this.workOvertime = workOvertime;
        this.festivalOvertime = festivalOvertime;
        this.holidayOvertime = holidayOvertime;
        this.askForLeave = askForLeave;
        this.businessTrip = businessTrip;
    }

    public AttendanceStatisticsVo(Integer attendanceId, String personNo, String personName, String groupName, Integer groupId, Integer absences, Integer lateNumber,
            Integer leaveEarly, Integer normalDays, Integer bAbsences, Integer bLateNumber, Integer bLeaveEarly, Integer bNormalDays, Integer cAbsences, Integer cLateNumber,
            Integer cLeaveEarly, Integer cNormalDays, Integer dAbsences, Integer dLateNumber, Integer dLeaveEarly, Integer dNormalDays, Integer workOvertime, Integer festivalOvertime,
            Integer holidayOvertime, Integer askForLeave, Integer businessTrip) {
        this.attendanceId = attendanceId;
        this.personNo = personNo;
        this.personName = personName;
        this.groupName = groupName;
        this.groupId = groupId;
        this.absences = absences;
        this.lateNumber = lateNumber;
        this.leaveEarly = leaveEarly;
        this.normalDays = normalDays;
        this.bAbsences = bAbsences;
        this.bLateNumber = bLateNumber;
        this.bLeaveEarly = bLeaveEarly;
        this.bNormalDays = bNormalDays;
        this.cAbsences = cAbsences;
        this.cLateNumber = cLateNumber;
        this.cLeaveEarly = cLeaveEarly;
        this.cNormalDays = cNormalDays;
        this.dAbsences = dAbsences;
        this.dLateNumber = dLateNumber;
        this.dLeaveEarly = dLeaveEarly;
        this.dNormalDays = dNormalDays;
        this.workOvertime = workOvertime;
        this.festivalOvertime = festivalOvertime;
        this.holidayOvertime = holidayOvertime;
        this.askForLeave = askForLeave;
        this.businessTrip = businessTrip;
    }
}
总结:
  1. maven依赖注意要全部倒入,其中包含多个扩展依赖.
  2. VO对象的封装使用的方法,我这里使用的构造器方法.
  3. 封装的属性的类型,必须与查询出来的类型相对应.
  4. 有一个不会拒绝的项目经理是多么可悲的一件事.
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/328176.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号