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

2023-12-03 12:58

本文主要是介绍【设计模式活用】之代码重构之DAO扮演多个职责的重构案例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在本次关于GPS优化需求项目时,发现相关功能菜单查询页面共同一个DAO接口实现类,紧接着我看了一下listAll,pre,next,countAll方法业务代码高度相似,此已说明该DAO扮演着非单一原则,其承担着 系统多个功能菜单的查询功能。

文章目录

  • 1.背景介绍
    • 1.1 业务分析
    • 1.2 思路分析
  • 2、相关类图
    • 2.1、executor类图
    • 2.2、context类图
  • 3、相关源码
    • 3.1、AbstractWhereExecutor
    • 3.2、InstalledGpsQueryExecutor
    • 3.3、TobeUploadGpsQueryExecutor
    • 3.4、UnInstalledGpsQueryExecutor
    • 3.5、UploadedGpsQueryExecutor
    • 3.6、调用方
  • 4、归纳总结

1.背景介绍

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

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

1.1 业务分析

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

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

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

源代码片段

@Overridepublic List<VCaAppInfo> pre(VCaAppInfoId ci, int pn, int defaultPageSize) {// TODO Auto-generated method stubStringBuffer 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())) { // 复审审批页面 显示自己审批的和信贷经理退回审批的// 150123sb.append(" and v.id.status in('23','30')");sb.append(" and v.AUserId=? ");listParams.add(ci.getUser().getUserId());} else if ("-27".equals(status)) { // 经销商上传GPS安装单 150302sb.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 addsb.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.2 思路分析

涉及四个功能菜单

  • 1、待上传GPS安装单
  • 2、GPS安装单列表
  • 3、GPS安装单未上传
  • 4、GPS安装单已上传

思路:分析如上四个菜单的查询特征,通过把相同和差异的抽象出来,即提取一个抽象类,通过模板方法,差异部分为抽象类子类,实现差异部分业务逻辑。

2、相关类图

2.1、executor类图

类图概览

2.2、context类图

context类图

3、相关源码

3.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();
}

3.2、InstalledGpsQueryExecutor

public class InstalledGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {/*** 标示*/protected String gpsFlow;/*** 审批人*/protected Integer approvalUserId;/*** 构造函数** @param context 上线文对象*/public InstalledGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected void prepare() {super.prepare();this.gpsFlow = dto.getGpsFlow();this.approvalUserId = dto.getUser().getUserId();}@Overrideprotected 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/21where.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) ");}}@Overrideprotected 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/21where.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) ");}}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-28".equals(dto.getStatus());}private boolean isMine(){return "mine".equals(gpsFlow);}
}

3.3、TobeUploadGpsQueryExecutor

public class TobeUploadGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {/*** 构造函数** @param context 上线文对象*/public TobeUploadGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected 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);});}@Overrideprotected 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);});}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-27".equals(dto.getStatus());}
}

3.4、UnInstalledGpsQueryExecutor

/*** @description: 车贷审批管理》GPS安装单未上传* @Date : 上午10:17 2017/11/17* @Author : 石冬冬-Heil Hitler(dongdong.shi@mljr.com)*/
public class UnInstalledGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {/*** 标示*/protected String gpsFlow;/*** 审批人*/protected Integer approvalUserId;/*** 构造函数** @param context 上线文对象*/public UnInstalledGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected void prepare() {super.prepare();this.gpsFlow = dto.getGpsFlow();this.approvalUserId = dto.getUser().getUserId();}@Overrideprotected 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) ");}}@Overrideprotected 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) ");}}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-29".equals(dto.getStatus());}private boolean isMine(){return "mine".equals(gpsFlow);}
}

3.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);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected 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);});}@Overrideprotected 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);});}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-33".equals(dto.getStatus());}
}

3.6、调用方

入口

4、归纳总结

如上,即使用了模板方法这个设计模式,模板方法也是最通常使用的,即把相同的逻辑骨架抽象处理,由子类实现各自的差异部门。

下面的是我的公众号二维码图片,欢迎关注,或公众号搜索【秋夜无霜】。
秋夜无霜

这篇关于【设计模式活用】之代码重构之DAO扮演多个职责的重构案例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/449537

相关文章

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(