【代码重构设计模式之运用】之代码重构之DAO扮演多个职责的重构案例

在本次关于GPS优化需求项目时,发现相关功能菜单查询页面共同一个DAO接口实现类,紧接着我看了一下listAll,pre,next,countAll方法业务代码高度相似,

此已说明该DAO扮演着非单一原则,其承担着 系统多个功能菜单的查询功能。

A.共同之处,就是查询共同表 ca_app_info,或者操作共同Hibernate对象VCaAppInfo

B.不同之处体现如下方面:1、包含HQL和SQL查询 。2、where条件不同(为了过滤数据以及根据页面表单条件动态判断拼加成一个StringBuffer对象(即SQL/HQL))

而涉及查询的四个方法中(listAll,pre,next,countAll方法业务代码高度相似),代码冗余,不利于维护。

因此,借此机遇,对涉及本期需求GPS查询 四个页面进行重构,提炼出四个单据的实现类,统一继承抽象类,内部维护相关SQL或者HQL查询逻辑,调用方只需构造上线文,

产生不同的实现类即可,提高可扩展,可维护性。重构前代码,点击链接,查看方法:listAll,pre,next,countAll,你就晓得了。

源代码片段:这代码多么。。。

@Override
	public List<VCaAppInfo> pre(VCaAppInfoId ci, int pn, int defaultPageSize) {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		sb.append("from VCaAppInfo v where 1=1");
		List<Object> listParams = new ArrayList<Object>();
		AbstractWhereExecutor<VCaAppInfoId> whereExecutor;
		WhereContext whereContext = new WhereContext(ci,sb,listParams,WhereContext.Strategy.HQL);
		String status = ci.getStatus();
		if (StringUtil.checkStatus(status)) {
			sb.append(" and v.id.status in (?)");
			listParams.add(status);
			sb.append(" and v.AUserId=? ");
			listParams.add(ci.getUser().getUserId());

			/*
			 * if("23".equals(status)){ //根据REFUSE_STATUS拒绝状态查询
			 * sb.append(" and v.refuseStatus in (?)");
			 * listParams.add(ci.getRefusestatus()); }else
			 * if("24".equals(status)){ sb.append(" and v.refuseStatus <> 3"); }
			 */

			if ("23".equals(status)) { // 根据REFUSE_STATUS拒绝状态查询
				sb.append(" and v.refuseStatus in (?)");
				listParams.add(ci.getRefusestatus());
			} else if ("24".equals(status) && !"3".equals(ci.getRefusestatus())) { // refusestatus
																					// =
																					// 0
																					// 1
																					// 终审
				sb.append(" and v.refuseStatus <> 3");
			} else if ("3".equals(ci.getRefusestatus())) { // 3 复核拒绝
				sb.append(" and v.refuseStatus = 3");
			}

		} else if ("80".equals(ci.getStatus())) { // 复审审批页面 显示自己审批的和信贷经理退回审批的
													// 150123
			sb.append(" and v.id.status in('23','30')");
			sb.append(" and v.AUserId=? ");
			listParams.add(ci.getUser().getUserId());
		} else if ("-27".equals(status)) { // 经销商上传GPS安装单 150302
			sb.append(" and (v.isGps ='0' or v.isGps ='2') and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and v.id.status not in('11','12') ");
			// 经销商用户只能查看该门店单子 其他用户查看所有
			Set<SyUserDealer> ds = ci.getUser().getSyUserDealers();
			if (ds.size() != 0) {
				sb.append(" and v.id.dealerCode in(");
				Iterator<SyUserDealer> it = ci.getUser().getSyUserDealers()
						.iterator();
				while (it.hasNext()) {
					SyUserDealer d = it.next();
					int dealerCode = d.getId().getDealerCode();
					sb.append(dealerCode + " ,");
				}
				String allhql = sb.substring(0, sb.length() - 1);
				allhql += ") ";
				sb.setLength(0);// 清空 后加上
				sb.append(allhql);
			}
		} else if ("-28".equals(status)) { // GPS维护 已上传GPS安装
			whereExecutor = new InstalledGpsQueryExecutor(whereContext);
			whereExecutor.execute();
		} else if ("-29".equals(status)) { // GPS维护
			whereExecutor = new UnInstallGpsQueryExecutor(whereContext);
			whereExecutor.execute();
		} else if ("-30".equals(status)) { // 贷后资料维护
			sb.append(" and (v.ALOANARRIVE is null or v.ALOANARRIVE!='1') and v.id.status='32' ");
			if (ci.getIsOld() != null) {
				sb.append(" and v.isOld=? ");
				listParams.add(ci.getIsOld());
			}
			if (ci.getPostLoanStatus() != null) {// 新车贷后资料上传状态(包括花乡的二手车 即先放款后抵押)
				if ("0".equals(ci.getPostLoanStatus())) {// 未上传
					sb.append(" and (v.postLoanStatus is null or v.postLoanStatus='0' ) ");
				} else if ("1".equals(ci.getPostLoanStatus())) {// 已上传
					sb.append(" and v.postLoanStatus='1' ");
				} else if ("2".equals(ci.getPostLoanStatus())) {// 审批退回
					sb.append(" and v.postLoanStatus='2' ");
				} else if ("3".equals(ci.getPostLoanStatus())) {// 审批通过
					sb.append(" and v.postLoanStatus='3' ");
				}
			}
		} else if ("-31".equals(status)) { // 贷后资料维护回退
			sb.append(" and v.ALOANARRIVE='1' and v.id.status='32' ");
		} else if ("-32".equals(status)) { // 新车等待上传贷后资料
			sb.append(" and v.id.status='32' and ifnull(v.ALOANARRIVE,'')!='1' ");
			if (ci.getIsOld() != null) {
				sb.append(" and v.isOld=? ");
				listParams.add(ci.getIsOld());
			}
			if (ci.getPostLoanStatus() != null) {
				if ("0".equals(ci.getPostLoanStatus())) {// 未上传
					sb.append(" and (v.postLoanStatus is null or v.postLoanStatus='0') ");
				} else if ("1".equals(ci.getPostLoanStatus())) {// 已上传
					sb.append(" and v.postLoanStatus='1' ");
				} else if ("2".equals(ci.getPostLoanStatus())) {// 审批退回
					sb.append(" and v.postLoanStatus='2' ");
				} else if ("3".equals(ci.getPostLoanStatus())) {// 审批通过
					sb.append(" and v.postLoanStatus='3' ");
				}
			} else {
				sb.append(" and ifnull(v.postLoanStatus,'')!='1' and ifnull(v.postLoanStatus,'')!='3' ");// 所有,不显示已上传的申请单和审批通过的
			}
			// 经销商用户只能查看该门店单子 其他用户查看所有
			Set<SyUserDealer> ds = ci.getUser().getSyUserDealers();
			if (ds.size() != 0) {
				sb.append(" and v.id.dealerCode in(");
				Iterator<SyUserDealer> it = ci.getUser().getSyUserDealers()
						.iterator();
				while (it.hasNext()) {
					SyUserDealer d = it.next();
					int dealerCode = d.getId().getDealerCode();
					sb.append(dealerCode + " ,");
				}
				String allhql = sb.substring(0, sb.length() - 1);
				allhql += ") ";
				sb.setLength(0);// 清空 后加上
				sb.append(allhql);
			}
		} else if ("-33".equals(status)) {// 经销商GPS安装列表,TODO zhaozhaoxin
											// 20170411 add
			sb.append(" and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and status in('15','16','17','18','19','25','26','27','28','29','32') ");
			// 经销商用户只能查看该门店单子 其他用户查看所有
			Set<SyUserDealer> ds = ci.getUser().getSyUserDealers();
			if (ds.size() != 0) {
				sb.append(" and v.id.dealerCode in(");
				Iterator<SyUserDealer> it = ci.getUser().getSyUserDealers()
						.iterator();
				while (it.hasNext()) {
					SyUserDealer d = it.next();
					int dealerCode = d.getId().getDealerCode();
					sb.append(dealerCode + " ,");
				}
				String allhql = sb.substring(0, sb.length() - 1);
				allhql += ") ";
				sb.setLength(0);// 清空 后加上
				sb.append(allhql);
			}
		} else {
			sb.append(" and v.id.status in (?)");
			listParams.add(status);

			// TODO zhaozhaoxin 20170308 add 进行分组查询
			if (isRoleQueryData(ci.getUser())) {
				getUserGroupIds(sb, ci.getUser(), status, true);
			} else {
				return null;
			}
		}
		if (ci.getFlowSeq() != null) {
			sb.append(" and v.flowSeq= ?");
			listParams.add(ci.getFlowSeq());
		}
		if (ci.getDealerName() != null) {
			sb.append(" and v.id.dealerName like ?");
			listParams.add("%" + ci.getDealerName() + "%");
		}

		if (ci.getAppCode() != null) {
			sb.append(" and v.id.appCode = ?");
			listParams.add(ci.getAppCode());
		}

		if (ci.getProppserName() != null) {
			sb.append(" and v.id.proppserName like ?");
			listParams.add("%" + ci.getProppserName() + "%");
		}

		if (ci.getIsLcv() != null) {
			sb.append(" and v.isLcv = ?");
			listParams.add(ci.getIsLcv());
		}
		if (ci.getAppTime() != null) {
			sb.append(" and date_format(v.id.appTime,'%Y%m%d') >= ?");
			listParams.add(DateUtil.getDateFormatE(ci.getAppTime()));
		}
		if (ci.getAppTime2() != null) {
			sb.append(" and date_format(v.id.appTime,'%Y%m%d') <= ?");
			listParams.add(DateUtil.getDateFormatE(ci.getAppTime2()));
		}
		if (ci.getUpdateTime1() != null) {
			sb.append(" and date_format(v.updateTime,'%Y%m%d') >= ?");
			listParams.add(DateUtil.getDateFormatE(ci.getUpdateTime1()));
		}
		if (ci.getUpdateTime2() != null) {
			sb.append(" and date_format(v.updateTime,'%Y%m%d') <= ?");
			listParams.add(DateUtil.getDateFormatE(ci.getUpdateTime2()));
		}
		if (ci.getLoanDate1() != null) {
			sb.append(" and date_format(v.loanTime,'%Y%m%d') >= ?");
			listParams.add(DateUtil.getDateFormatE(ci.getLoanDate1()));
		}
		if (ci.getLoanDate2() != null) {
			sb.append(" and date_format(v.loanTime,'%Y%m%d') <= ?");
			listParams.add(DateUtil.getDateFormatE(ci.getLoanDate2()));
		}
		sb.append(" order by v.updateTime asc");// 从小到大排序 先提交的在前面

		List<VCaAppInfo> result = queryByHql(sb.toString(), pn,
				defaultPageSize, listParams.toArray());
		return result;
	}

涉及四个系统功能菜单

1、车贷申请管理》待上传GPS安装单

2、车贷申请管理》GPS安装单列表

3、车贷审批管理》GPS安装单未上传

4、车贷审批管理》GPS安装单已上传

1、相关类图

1.1、executor类图

1.2、context类图

2、相关源码

2.1、抽象类:AbstractWhereExecutor

public abstract class AbstractWhereExecutor<T> implements Predicate<WhereContext> {
    /**
     * 上线文
     */
    protected WhereContext<T> context;
    /**
     * 参数DTO
     */
    protected T dto;
    /**
     * 查询条件
     */
    protected StringBuffer queryWhere;

    /**
     * 构造函数
     * @param context 上线文对象
     */
    public AbstractWhereExecutor(WhereContext<T> context) {
        this.context = context;
    }

    /**
     * 处理接口
     */
    public void execute() {
        this.execute((e)->{});
    }

    /**
     * 处理接口
     * @param after
     */
    public void execute(Consumer<WhereContext> after) {
        // 初始化
        this.prepare();
        // 检查参数
        this.check(context);
        // 执行鉴定
        if(this.test(context)){
            switch (context.getStrategy()){
                case SQL:
                    sql();
                    break;
                case HQL:
                    hql();
                    break;
                default:
                    break;
            }
        }
        // 后置处理
        after.accept(context);
    }

    /**
     * 参数检查
     * @param context
     */
    protected void check(WhereContext context){
        Assert.notNull(context.getDto(),"DTO对象为空");
        Assert.notNull(context.getStrategy(),"strategy为空");
    }

    /**
     * 初始化参数
     */
    protected void prepare(){
        this.dto = this.context.getDto();
        this.queryWhere = this.context.getQueryWhere();
    }
    /**
     * 由子类实现具体处理SQL条件
     */
    protected abstract void sql();
    /**
     * 由子类实现具体处理HQL条件
     */
    protected abstract void hql();
}

2.2、实现类:InstalledGpsQueryExecutor

public class InstalledGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {
    /**
     * 标示
     */
    protected String gpsFlow;
    /**
     * 审批人
     */
    protected Integer approvalUserId;

    /**
     * 构造函数
     *
     * @param context 上线文对象
     */
    public InstalledGpsQueryExecutor(WhereContext context) {
        super(context);
    }

    @Override
    protected void check(WhereContext context) {
        super.check(context);
        SyUser sessionUser = dto.getUser();
        Assert.notNull(sessionUser,"sessionUser为空");
    }

    @Override
    protected void prepare() {
        super.prepare();
        this.gpsFlow = dto.getGpsFlow();
        this.approvalUserId = dto.getUser().getUserId();
    }

    @Override
    protected void sql() {
        VCaAppInfoId dto = super.dto;
        StringBuffer where = super.queryWhere;
        if(this.isMine()){
            where.append(" and exists(select 1 from ca_gps_flow f where f.app_code = v.app_code and f.flow_step = 0 and f.approval_user_id = "+this.approvalUserId+") ");
        }
        where.append(" and v.status not in (11,13) and v.is_Gps ='2' and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null");
        if(!StringUtil.isBlank(dto.getProvince())){
            where.append(" and exists(select 1 from Sy_Dealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealer_Code =  v.dealer_Code) ");
        }
        if (!StringUtil.isBlank(dto.getPostLoanStatus())) {
            //由于manual_audit_code多个时以";"分割,所以需要使用FIND_IN_SET函数处理 add by 石冬冬 on 2017/9/21
            where.append(" and v.app_code IN (SELECT app_code FROM Ca_Car_Gps WHERE del_status=1 and FIND_IN_SET ("+dto.getPostLoanStatus()+",replace(manual_audit_code,';',','))>0 ");
            where.append(" GROUP BY app_code) ");
        }
    }

    @Override
    protected void hql() {
        VCaAppInfoId dto = super.dto;
        StringBuffer where = super.queryWhere;
        if(this.isMine()){
            where.append(" and exists(select 1 from CaGpsFlow f where f.appCode = v.id.appCode and f.flowStep = 0 and f.approvalUserId = " + this.approvalUserId+")");
        }
        where.append(" and v.id.status not in (11,13) and v.isGps ='2' and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null");
        if(!StringUtil.isBlank(dto.getProvince())){
            where.append(" and exists(select 1 from SyDealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealerCode =  v.id.dealerCode) ");
        }
        if (!StringUtil.isBlank(dto.getPostLoanStatus())) {
            //由于manual_audit_code多个时以";"分割,所以需要使用FIND_IN_SET函数处理 add by 石冬冬 on 2017/9/21
            where.append(" and v.id.appCode IN (SELECT appCode FROM CaCarGps WHERE delStatus=1 and find_in_set("+dto.getPostLoanStatus()+",replace(manualAuditCode,';',','))>0 ");
            where.append(" GROUP BY appCode) ");
        }
    }

    @Override
    public boolean test(WhereContext context) {
        VCaAppInfoId dto = (VCaAppInfoId)context.getDto();
        return "-28".equals(dto.getStatus());
    }

    private boolean isMine(){
        return "mine".equals(gpsFlow);
    }
}

2.3、实现类:TobeUploadGpsQueryExecutor

public class TobeUploadGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {
    /**
     * 构造函数
     *
     * @param context 上线文对象
     */
    public TobeUploadGpsQueryExecutor(WhereContext context) {
        super(context);
    }

    @Override
    protected void check(WhereContext context) {
        super.check(context);
        SyUser sessionUser = dto.getUser();
        Assert.notNull(sessionUser,"sessionUser为空");
    }
    @Override
    protected void sql() {
        StringBuffer where = super.queryWhere;
        SyUser sessionUser = dto.getUser();
        where.append(" and (v.is_Gps ='0' or v.is_Gps ='2') and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null and v.status not in('11','12') ");
        GpsUtil.appendDealerCodes(sessionUser,(list) -> {
            String condition = MessageFormat.format(" and v.dealer_Code in({0})", StringUtils.join(list,","));
            where.append(condition);
        });
    }

    @Override
    protected void hql() {
        StringBuffer where = super.queryWhere;
        SyUser sessionUser = dto.getUser();
        where.append(" and (v.isGps ='0' or v.isGps ='2') and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and v.id.status not in('11','12') ");
        GpsUtil.appendDealerCodes(sessionUser,(list) -> {
            String condition = MessageFormat.format(" and v.id.dealerCode in({0})", StringUtils.join(list,","));
            where.append(condition);
        });
    }

    @Override
    public boolean test(WhereContext context) {
        VCaAppInfoId dto = (VCaAppInfoId)context.getDto();
        return "-27".equals(dto.getStatus());
    }
}

2.4、实现类:UnInstalledGpsQueryExecutor 

/**
 * @description: 车贷审批管理》GPS安装单未上传
 * @Date : 上午10:17 2017/11/17
 * @Author : 石冬冬-Heil Hitler([email protected])
 */
public class UnInstalledGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {
    /**
     * 标示
     */
    protected String gpsFlow;
    /**
     * 审批人
     */
    protected Integer approvalUserId;
    /**
     * 构造函数
     *
     * @param context 上线文对象
     */
    public UnInstalledGpsQueryExecutor(WhereContext context) {
        super(context);
    }

    @Override
    protected void check(WhereContext context) {
        super.check(context);
        SyUser sessionUser = dto.getUser();
        Assert.notNull(sessionUser,"sessionUser为空");
    }

    @Override
    protected void prepare() {
        super.prepare();
        this.gpsFlow = dto.getGpsFlow();
        this.approvalUserId = dto.getUser().getUserId();
    }

    @Override
    protected void sql() {
        StringBuffer where = super.queryWhere;
        if(this.isMine()){
            where.append(" and exists(select 1 from ca_gps_flow f where f.app_code = v.app_code and f.flow_step = 0 and f.approval_user_id = "+this.approvalUserId+")");
        }
        where.append(" and v.status not in (11,13) and v.is_Gps ='0' and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null");
        if(!StringUtil.isBlank(dto.getProvince())){
            where.append(" and exists(select 1 from Sy_Dealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealer_Code =  v.dealer_Code) ");
        }
    }

    @Override
    protected void hql() {
        VCaAppInfoId dto = super.dto;
        StringBuffer where = super.queryWhere;
        if(this.isMine()){
            where.append(" and exists(select 1 from CaGpsFlow f where f.appCode = v.id.appCode and f.flowStep = 0 and f.approvalUserId = "+this.approvalUserId+")");
        }
        where.append(" and v.id.status not in (11,13) and v.isGps ='0' and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null");
        if(!StringUtil.isBlank(dto.getProvince())){
            where.append(" and exists(select 1 from SyDealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealerCode =  v.id.dealerCode) ");
        }
    }

    @Override
    public boolean test(WhereContext context) {
        VCaAppInfoId dto = (VCaAppInfoId)context.getDto();
        return "-29".equals(dto.getStatus());
    }

    private boolean isMine(){
        return "mine".equals(gpsFlow);
    }
}

2.5、实现类:UploadedGpsQueryExecutor

public class UploadedGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {
    private final String STATUS_SCOPE = "'15','16','17','18','19','25','26','27','28','29','32'";
    /**
     * 构造函数
     *
     * @param context 上线文对象
     */
    public UploadedGpsQueryExecutor(WhereContext context) {
        super(context);
    }

    @Override
    protected void check(WhereContext context) {
        super.check(context);
        SyUser sessionUser = dto.getUser();
        Assert.notNull(sessionUser,"sessionUser为空");
    }

    @Override
    protected void sql() {
        VCaAppInfoId dto = super.dto;
        StringBuffer where = super.queryWhere;
        SyUser sessionUser = dto.getUser();
        where.append(" and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null and status in("+STATUS_SCOPE+") ");
        GpsUtil.appendDealerCodes(sessionUser,(list) -> {
            String condition = MessageFormat.format(" and v.dealer_Code in({0})", StringUtils.join(list,","));
            where.append(condition);
        });
    }

    @Override
    protected void hql() {
        VCaAppInfoId dto = super.dto;
        StringBuffer where = super.queryWhere;
        SyUser sessionUser = dto.getUser();
        where.append(" and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and status in("+STATUS_SCOPE+") ");
        GpsUtil.appendDealerCodes(sessionUser,(list) -> {
            String condition = MessageFormat.format(" and v.id.dealerCode in({0})", StringUtils.join(list,","));
            where.append(condition);
        });
    }

    @Override
    public boolean test(WhereContext context) {
        VCaAppInfoId dto = (VCaAppInfoId)context.getDto();
        return "-33".equals(dto.getStatus());
    }
}

2.6、调用方

发布了46 篇原创文章 · 获赞 27 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/shichen2010/article/details/78592821