手写Java代码生成工具(四)生成mapper.xml文件

154 阅读10分钟

前言

写博客是为了记录和分享自己的学习,所分享内容是网上的资源,由于非原创项目,主要分享学习思路,只展示贴图部分代码(本人不分享本项目源码,支持项目付费


一、创建mapper.xml文件以及生成XML 头部信息

        //创建MapperXml包
        File folder = new File(Constants.PATH_MAPPER_XML);
        if(!folder.exists()){
            folder.mkdirs();
        }

        String className= tableInfo.getBeanName()+Constants.SUFFIX_BEAN_MAPPER;
        //创建MapperXml文件
        File file = new File(folder,className+".xml");
        OutputStream out=null;
        OutputStreamWriter writer=null;
        BufferedWriter bw=null;
    
        out=new FileOutputStream(file);
        writer=new OutputStreamWriter(out,"UTF-8");
        bw=new BufferedWriter(writer);

        bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">");
        bw.newLine();
        bw.write("<mapper namespace=\""+Constants.PACKAGE_MAPPER+"."+className+"\">");
        bw.newLine();
        bw.newLine();
  
  1. 创建MapperXml包
  • File folder = new File(Constants.PATH_MAPPER_XML);:通过一个常量路径创建一个表示MapperXml包的File对象。
  • if(!folder.exists()){ folder.mkdirs(); }:如果该包对应的文件路径不存在,则创建这个目录。
  1. 创建 MapperXml 文件
  • String className = tableInfo.getBeanName()+Constants.SUFFIX_BEAN_MAPPER;:获取表信息中的 bean 名称,并加上特定后缀组成文件名。
  • File file = new File(folder,className+".xml");:在已创建的MapperXml包中创建一个以特定名称命名的 XML 文件。
  1. 准备写入文件
  • OutputStream out = null;、OutputStreamWriter writer = null;、BufferedWriter bw = null;:声明输出流、输出流写入器和缓冲写入器,用于向文件写入内容。
  • out = new FileOutputStream(file);:创建一个文件输出流,指向要创建的 XML 文件。
  • writer = new OutputStreamWriter(out,"UTF-8");:使用指定的字符编码创建一个输出流写入器,包裹文件输出流。
  • bw = new BufferedWriter(writer);:创建一个缓冲写入器,包裹输出流写入器,以提高写入效率。
  1. 写入内容
  • bw.write("\n" + "");:向 XML 文件写入 XML 声明和 DTD 定义。
  • bw.newLine();:写入一个换行符。
  • bw.write("<mapper namespace=""+Constants.PACKAGE_MAPPER+"."+className+"">");:写入标签的开头部分,并设置命名空间为特定的包名和类名。

二、生成实体映射

           //生成实体映射
            bw.write("\t<!--实体映射-->");
            bw.newLine();

            String dtoClassName=Constants.PACKAGE_PO+"."+tableInfo.getBeanName()+Constants.SUFFIX_BEAN_PO;
            bw.write("\t<resultMap id=\""+tableInfo.getBeanName()+"ResultMap\" type=\""+dtoClassName+"\">");
            bw.newLine();

            FieldInfo isField=null;
            Map<String, List<FieldInfo>> keyIndexMap = tableInfo.getKeyIndexMap();
            for(Map.Entry<String,List<FieldInfo>> entry:keyIndexMap.entrySet()){
                if("PRIMARY".equals(entry.getKey())){
                    List<FieldInfo> fieldInfoList = entry.getValue();
                    if(fieldInfoList.size()==1){
                        isField=fieldInfoList.get(0);
                        break;
                    }
                }
            }

            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                    bw.write("\t\t<!-- "+fieldInfo.getComment()+" -->");
                    bw.newLine();
                    String key="";
                    if(isField!=null && fieldInfo.getPropertyName().equals(isField.getFieldName())){
                        key="id";
                    }else {
                        key="result";
                    }
                    bw.write("\t\t<"+key+" column=\""+fieldInfo.getFieldName()+"\" property=\""+fieldInfo.getPropertyName()+"\"/>");
                    bw.newLine();
            }

            bw.write("\t</resultMap>");
            bw.newLine();
            bw.newLine();

这段代码在之前创建的 MyBatis Mapper XML 文件中生成实体映射部分。具体来说,它创建了一个名为tableInfo.getBeanName() + "ResultMap"的结果映射,用于将数据库查询结果映射到指定的实体类。

  1. 创建结果映射
  • String dtoClassName = Constants.PACKAGE_PO + "." + tableInfo.getBeanName() + Constants.SUFFIX_BEAN_PO;:构建实体类的全限定名。
  • bw.write("\t<resultMap id="" + tableInfo.getBeanName() + "ResultMap" type="" + dtoClassName + "">");:开始定义一个结果映射,指定其 ID 和对应的实体类类型。
  1. 确定主键字段 通过遍历tableInfo.getKeyIndexMap(),查找键为"PRIMARY"的条目,获取主键字段信息。如果主键只有一个字段,将其存储在isField变量中。
  2. 生成字段映射 遍历tableInfo.getFieldIofoList(),对于每个字段: 根据字段是否为主键确定映射的标签类型:如果是主键字段,使用id标签;否则,使用result标签。然后写入字段映射信息,包括数据库列名和实体类属性名。

三、生成通用sql片段

//通用查询列表
            bw.write("\t<!--通用查询列表-->");
            bw.newLine();
            bw.write("\t<sql id=\""+BASE_COLUMN_LIST+"\">");
            bw.newLine();
            StringBuilder sb=new StringBuilder();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                sb.append(fieldInfo.getFieldName()).append(",");
            }
            String sbStr=sb.substring(0,sb.lastIndexOf(","));
            bw.write("\t\t"+sbStr);
            bw.newLine();
            bw.write("\t</sql>");
            bw.newLine();
            bw.newLine();

            //基础查询条件
            bw.write("\t<!--基础查询条件-->");
            bw.newLine();
            bw.write("\t<sql id=\""+BASE_QUERY_CONDITION+"\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                String stringQuery="";
                if(ArrayUtils.contains(Constants.SQL_STRING_TYPES,fieldInfo.getSqlType())){
                    stringQuery="and query."+fieldInfo.getPropertyName()+" !=''";
                }
                bw.write("\t\t<if test=\"query."+fieldInfo.getPropertyName()+" != null "+stringQuery+"\">");
                bw.newLine();
                bw.write("\t\t\tand "+fieldInfo.getFieldName()+" = #{query."+fieldInfo.getPropertyName()+"}");
                bw.newLine();
                bw.write("\t\t</if>");
                bw.newLine();
            }
            bw.write("\t</sql>");
            bw.newLine();
            bw.newLine();


            //拓展查询条件
            bw.write("\t<!--拓展查询条件-->");
            bw.newLine();
            bw.write("\t<sql id=\""+BASE_QUERY_CONDITION_EXTEND+"\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldExtendInfoList()){
                String andWhere="";
                if(ArrayUtils.contains(Constants.SQL_STRING_TYPES,fieldInfo.getSqlType())){
                    andWhere="and "+fieldInfo.getFieldName()+" like concat('%',#{query."+fieldInfo.getPropertyName()+"},'%')";
                }else if(ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES,fieldInfo.getSqlType())||ArrayUtils.contains(Constants.SQL_DATE_TYPE,
                        fieldInfo.getSqlType())){
                    if(fieldInfo.getPropertyName().endsWith(Constants.SUFFIX_BEAN_QUREY_DATE_START)){
                        andWhere="<![CDATA[ and "+fieldInfo.getFieldName()+">=str_to_date(#{query."+fieldInfo.getPropertyName()+"}, '%Y-%m-%d') ]]>";
                    } else if (fieldInfo.getPropertyName().endsWith(Constants.SUFFIX_BEAN_QUREY_DATE_END)) {
                        andWhere="<![CDATA[ and "+fieldInfo.getFieldName()+"< date_sub(str_to_date(#{query."+fieldInfo.getPropertyName()+"}, '%Y-%m-%d'),"+
                    "interval -1 day) ]]>";
                    }
                }
                bw.write("\t\t<if test=\"query."+fieldInfo.getPropertyName()+" != null and query."+fieldInfo.getPropertyName()+" !=''\">");
                bw.newLine();
//                bw.write("\t\t\tand id = #{query."+fieldInfo.getPropertyName()+" }");
                bw.write("\t\t\t"+andWhere);
                bw.newLine();
                bw.write("\t\t</if>");
                bw.newLine();
            }
            bw.write("\t</sql>");
            bw.newLine();
            bw.newLine();

            //通用查询条件
            bw.write("\t<!--通用查询条件-->");
            bw.newLine();
            bw.write("\t<sql id=\""+QUERY_CONDITION+"\">");
            bw.newLine();
            bw.write("\t\t<where>");
            bw.newLine();
            bw.write("\t\t\t<include refid=\""+BASE_QUERY_CONDITION+"\"/>");
            bw.newLine();
            bw.write("\t\t\t<include refid=\""+BASE_QUERY_CONDITION_EXTEND+"\"/>");
            bw.newLine();
            bw.write("\t\t</where>");
            bw.newLine();
            bw.write("\t</sql>");
            bw.newLine();
            bw.newLine();

这段代码在Mapper XML 文件中继续添加了通用查询列表和不同类型的查询条件相关的内容,方便我们在之后的片段调用。

  1. 通用查询列表
  • 定义 SQL 片段:bw.write("\t<sql id=""+BASE_COLUMN_LIST+"">");开始定义一个名为BASE_COLUMN_LIST的 SQL 片段。
  • 遍历字段列表构建查询列:遍历tableInfo.getFieldIofoList(),将每个字段的名称拼接起来,最后写入 SQL 片段中。
  1. 基础查询条件
  • 定义 SQL 片段:bw.write("\t<sql id=""+BASE_QUERY_CONDITION+"">");开始定义一个名为BASE_QUERY_CONDITION的 SQL 片段。
  • 遍历字段列表生成条件判断:对于每个字段,根据字段类型判断是否为字符串类型,如果是,则生成相应的查询条件。使用标签进行条件判断,如果查询参数不为空且不是空字符串,则添加查询条件。
  1. 拓展查询条件
  • 定义 SQL 片段:bw.write("\t<sql id=""+BASE_QUERY_CONDITION_EXTEND+"">");开始定义一个名为BASE_QUERY_CONDITION_EXTEND的 SQL 片段。
  • 遍历扩展字段列表生成条件判断:对于每个扩展字段,根据字段类型生成不同的查询条件。如果是字符串类型,则进行模糊查询;如果是日期类型,则根据特定的后缀判断是开始日期还是结束日期,并生成相应的日期范围查询条件。
  1. 通用查询条件
  • 定义 SQL 片段:bw.write("\t<sql id=""+QUERY_CONDITION+"">");开始定义一个名为QUERY_CONDITION的 SQL 片段。
  • 使用where标签包裹查询条件:在这个 SQL 片段中,引入了之前定义的基础查询条件和拓展查询条件。

四、生成查询方法

根据参数查询集合

            //根据参数查询集合
            bw.write("\t<!--根据参数查询集合-->");
            bw.newLine();

            bw.write("\t<select id=\"selectList\" resultMap=\""+tableInfo.getBeanName()+"ResultMap\">");
            bw.newLine();
            bw.write("\t\tSELECT <include refid=\""+BASE_COLUMN_LIST+"\" /> FROM "+tableInfo.getTableName()+
                    " <include refid=\"" +QUERY_CONDITION+"\" />");
            bw.newLine();
            bw.write("\t\t<if test=\"query.orderBy!=null\">order by ${query.orderBy} </if>");
            bw.newLine();
            bw.write("\t\t<if test=\"query.SimplePage!=null\">limit #{query.SimplePage.start}, #{query.SimplePage.end} </if>");
            bw.newLine();
            bw.write("\t</select>");
            bw.newLine();
            bw.newLine();
  • bw.write("\t<select id="selectList" resultMap=""+tableInfo.getBeanName()+"ResultMap">");开始定义一个名为selectList的查询方法,并指定结果映射为前面生成的结果映射。
  • 构建查询语句: bw.write("\t\tSELECT <include refid=""+BASE_COLUMN_LIST+"" /> FROM "+tableInfo.getTableName()+ " <include refid="" +QUERY_CONDITION+"" />");使用标签引入通用查询列和通用查询条件,构建查询语句从指定的表中查询数据。
  • 处理排序: bw.write("\t\t<if test="query.orderBy!=null">order by ${query.orderBy} ")如果查询参数中包含排序字段,则使用动态 SQL 添加排序条件。这里使用了{}语法,需要注意防止 SQL 注入。
  • 处理分页: bw.write("\t\t<if test="query.SimplePage!=null">limit #{query.SimplePage.start}, #{query.SimplePage.end} ");如果查询参数中包含分页信息,则使用动态 SQL 添加分页条件,通过#{}语法传入分页的起始位置和结束位置。

根据参数查询数量

            //根据参数查询数量
            bw.write("\t<!--根据参数查询数量-->");
            bw.newLine();
            bw.write("\t<select id=\"selectCount\" resultType=\"java.lang.Integer\">");
            bw.newLine();
            bw.write("\t\tSELECT count(1) FROM "+tableInfo.getTableName()+ " <include refid=\"" +QUERY_CONDITION+"\" />");
            bw.newLine();
            bw.write("\t</select>");
            bw.newLine();
            bw.newLine();
  • bw.write("\t<select id="selectCount" resultType="java.lang.Integer">");开始定义一个名为selectCount的查询方法,并指定结果类型为java.lang.Integer,表示返回一个整数结果,即数据记录的数量。
  • 构建查询语句: bw.write("\t\tSELECT count(1) FROM "+tableInfo.getTableName()+ " <include refid="" +QUERY_CONDITION+"" />");使用SELECT count(1)语句从指定的表中查询数据记录数量,并通过标签引入通用查询条件,以确保只统计满足特定条件的数据记录。

单条插入

             //单条插入
            bw.write("\t<!--插入-匹配有值的字段-->");
            bw.newLine();
            bw.write("\t<insert id=\"insert\" parameterType=\""+dtoClassName+"\">");
            bw.newLine();

            FieldInfo autoIncrementField=null;
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                if(fieldInfo.getAutoIncrement()!=null&&fieldInfo.getAutoIncrement()){
                    autoIncrementField=fieldInfo;
                    break;
                }
            }
            if(autoIncrementField!=null){
                bw.write("\t\t<selectKey keyProperty=\"bean."+autoIncrementField.getPropertyName()+"\" resultType=\""+autoIncrementField.getJavaType()
                        +"\" order=\"AFTER\">");
                bw.newLine();
                bw.write("\t\t\tSELECT 0");
                bw.newLine();
                bw.write("\t\t</selectKey>");
                bw.newLine();
            }

            bw.write("\t\tinsert into "+tableInfo.getTableName());
            bw.newLine();
            bw.write("\t\t<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                bw.write("\t\t\t<if test=\"bean."+fieldInfo.getPropertyName()+" != null\">");
                bw.newLine();
                bw.write("\t\t\t\t"+fieldInfo.getFieldName()+", ");
                bw.newLine();
                bw.write("\t\t\t</if>");
                bw.newLine();
            }
            bw.write("\t\t</trim>");
            bw.newLine();
            bw.write("\t\t<trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                bw.write("\t\t\t<if test=\"bean."+fieldInfo.getPropertyName()+" != null\">");
                bw.newLine();
                bw.write("\t\t\t\t#{bean."+fieldInfo.getPropertyName()+"}, ");
                bw.newLine();
                bw.write("\t\t\t</if>");
                bw.newLine();
            }
            bw.write("\t\t</trim>");
            bw.newLine();
            bw.write("\t</insert>");
            bw.newLine();
            bw.newLine();
  • 定义插入方法: bw.write("\t<insert id="insert" parameterType=""+dtoClassName+"">");开始定义一个名为insert的插入方法,并指定参数类型为实体类的全限定名。
  • 处理自增字段: 遍历字段列表查找自增字段:通过遍历tableInfo.getFieldIofoList(),查找标记为自增的字段,并将其存储在autoIncrementField变量中。
  • 构建插入语句: bw.write("\t\tinsert into "+tableInfo.getTableName());指定要插入数据的表名。 使用trim标签处理字段列表和值列表: 第一个trim标签用于构建字段列表,遍历实体类的字段,如果字段值不为空,则将字段名添加到列表中。 第二个trim标签用于构建值列表,同样遍历实体类的字段,如果字段值不为空,则将#{bean.属性名}形式的占位符添加到列表中。

插入或更新

            //插入或更新
            bw.write("\t<!--插入或更新 -->");
            bw.newLine();
            bw.write("\t<insert id=\"insertOrUpdate\" parameterType=\""+dtoClassName+"\">");
            bw.newLine();

            bw.write("\t\tinsert into "+tableInfo.getTableName());
            bw.newLine();
            bw.write("\t\t<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                bw.write("\t\t\t<if test=\"bean."+fieldInfo.getPropertyName()+" != null\">");
                bw.newLine();
                bw.write("\t\t\t\t"+fieldInfo.getFieldName()+", ");
                bw.newLine();
                bw.write("\t\t\t</if>");
                bw.newLine();
            }
            bw.write("\t\t</trim>");
            bw.newLine();
            bw.write("\t\t<trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                bw.write("\t\t\t<if test=\"bean."+fieldInfo.getPropertyName()+" != null\">");
                bw.newLine();
                bw.write("\t\t\t\t#{bean."+fieldInfo.getPropertyName()+"}, ");
                bw.newLine();
                bw.write("\t\t\t</if>");
                bw.newLine();
            }
            bw.write("\t\t</trim>");
            bw.newLine();

            bw.write("\t\tON DUPLICATE KEY UPDATE ");
            bw.newLine();

            Map<String,String> keyTempMap=new HashMap<>();
            for(Map.Entry<String,List<FieldInfo>> entry:keyIndexMap.entrySet()){
                List<FieldInfo> fieldInfoList = entry.getValue();
                for(FieldInfo fieldInfo:fieldInfoList) {
                    keyTempMap.put(fieldInfo.getFieldName(),fieldInfo.getFieldName());
                }
            }

            bw.write("\t\t<trim prefix=\"\" suffix=\"\" suffixOverrides=\",\">");
            bw.newLine();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                if(keyTempMap.get(fieldInfo.getFieldName())!=null){
                    continue;
                }
                bw.write("\t\t\t<if test=\"bean."+fieldInfo.getPropertyName()+" != null\">");
                bw.newLine();
                bw.write("\t\t\t\t"+fieldInfo.getFieldName()+" = VALUES("+fieldInfo.getFieldName()+"),");
                bw.newLine();
                bw.write("\t\t\t</if>");
               bw.newLine();
            }
            bw.write("\t\t</trim>");
            bw.newLine();
            bw.write("\t</insert>");
            bw.newLine();
            bw.newLine();
  • 定义插入或更新方法: bw.write("\t<insert id="insertOrUpdate" parameterType=""+dtoClassName+"">");开始定义一个名为insertOrUpdate的方法,并指定参数类型为实体类的全限定名。
  • 构建插入语句部分: 与单条插入方法类似,构建插入语句,包括指定表名、使用标签处理字段列表和值列表。遍历实体类的字段,如果字段值不为空,则将字段名和对应的值占位符添加到插入语句中。
  • 处理重复键冲突: bw.write("\t\tON DUPLICATE KEY UPDATE ");指定当发生重复键冲突时执行更新操作。
  • 构建更新语句: 首先,遍历表的键索引信息,将所有键字段存储在keyTempMap中。 然后,再次遍历实体类的字段列表,对于非键字段,如果字段值不为空,则生成更新语句,形式为字段名 = VALUES(字段名)。使用标签去除多余的逗号后缀。

批量插入

            //批量插入
            bw.write("\t<!--批量插入-->");
            bw.newLine();
            bw.write("\t<insert id=\"insertBatch\" parameterType=\""+dtoClassName+"\" >");
            bw.newLine();
            StringBuffer insertFieldBuffer=new StringBuffer();
            StringBuffer insertPropertyBuffer=new StringBuffer();
            for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                if(fieldInfo.getAutoIncrement()){
                    continue;
                }

                insertFieldBuffer.append(fieldInfo.getFieldName()).append(",");

                insertPropertyBuffer.append("#{item.").append(fieldInfo.getPropertyName()).append("},");
            }
            String insertFieldBuddefStr=insertFieldBuffer.substring(0,insertFieldBuffer.lastIndexOf(","));
            bw.write("\t\tinsert into "+tableInfo.getTableName()+"("+insertFieldBuddefStr+")values");
            bw.newLine();
            bw.write("\t\t<foreach collection=\"list\" item=\"item\" separator=\",\">");
            bw.newLine();

            String insertPropertyBuddefStr=insertPropertyBuffer.substring(0,insertPropertyBuffer.lastIndexOf(","));
            bw.write("\t\t\t("+insertPropertyBuddefStr+")");
            bw.newLine();
            bw.write("\t\t</foreach>");
            bw.newLine();
            bw.write("\t</insert>");
            bw.newLine();
            bw.newLine();
  • 定义批量插入方法: bw.write("\t<insert id="insertBatch" parameterType=""+dtoClassName+"" >");开始定义一个名为insertBatch的方法,并指定参数类型为实体类的全限定名。
  • 构建插入字段和属性列表: 遍历表的字段信息列表:对于每个字段,如果不是自增字段,则将字段名添加到insertFieldBuffer中,将#{item.属性名}形式的占位符添加到insertPropertyBuffer中。 提取字段和属性列表字符串:去除最后一个逗号,得到用于插入语句的字段列表字符串和属性列表字符串。
  • 构建批量插入语句: bw.write("\t\tinsert into "+tableInfo.getTableName()+"("+insertFieldBuddefStr+")values");指定要插入数据的表名和字段列表。
  • 使用标签进行循环插入: bw.write("\t\t<foreach collection="list" item="item" separator=",">");表示遍历参数中的列表,每个元素称为item,元素之间用逗号分隔。 bw.write("\t\t\t("+insertPropertyBuddefStr+")");构建每个元素的插入值列表。 bw.write("\t\t/foreach");结束foreach标签。

 for(Map.Entry<String,List<FieldInfo>> entry:keyIndexMap.entrySet()){
                List<FieldInfo> fieldInfoList = entry.getValue();

                Integer index=0;
                StringBuilder methodName = new StringBuilder();
                StringBuilder methodParamName = new StringBuilder();
                for(FieldInfo fieldInfo:fieldInfoList){
                    index++;
                    methodName.append(StringUtils.uperCaseFirstLetter(fieldInfo.getPropertyName()));
                    methodParamName.append(fieldInfo.getFieldName()+"=#{"+fieldInfo.getPropertyName()+"}");
                    if(index<fieldInfoList.size()){
                        methodName.append("And");
                        methodParamName.append("and");
                    }
                }

                //查询
                bw.write("\t<!-- 根据"+methodName+"查询 -->");
                bw.newLine();
                bw.write("\t<select id=\"selectBy"+ methodName+"\" resultMap=\""+tableInfo.getBeanName()+"ResultMap\">");
                bw.newLine();
                bw.write("\t\tselect <include refid=\""+BASE_COLUMN_LIST+"\"/> from "+tableInfo.getTableName()+" where "+methodParamName);
                bw.newLine();
                bw.write("\t</select>");
                bw.newLine();
                bw.newLine();

                //更新
                bw.write("\t<!-- 根据"+methodName+"更新 -->");
                bw.newLine();
                bw.write("\t<update id=\"updateBy"+ methodName+"\" parameterType=\""+dtoClassName+"\">");
                bw.newLine();
                bw.write("\t\t update "+tableInfo.getTableName());
                bw.newLine();
                bw.write("\t\t <set>");
                bw.newLine();
                for(FieldInfo fieldInfo:tableInfo.getFieldIofoList()){
                    bw.write("\t\t\t<if test=\"bean."+fieldInfo.getPropertyName()+"!=null\">");
                    bw.newLine();
                    bw.write("\t\t\t\t"+fieldInfo.getFieldName()+" = #{bean."+fieldInfo.getPropertyName()+"},");
                    bw.newLine();
                    bw.write("\t\t\t</if>");
                    bw.newLine();
                }
                bw.write("\t\t </set>");
                bw.newLine();
                bw.write("\t\t where "+methodParamName);
                bw.newLine();
                bw.write("\t</update>");
                bw.newLine();
                bw.newLine();

                //删除
                bw.write("\t<!-- 根据"+methodName+"删除 -->");
                bw.newLine();
                bw.write("\t<delete id=\"deleteBy"+ methodName+"\">");
                bw.newLine();
                bw.write("\t\t delete from "+tableInfo.getTableName()+" where "+methodParamName);
                bw.newLine();
                bw.write("\t</delete>");
                bw.newLine();
                bw.newLine();

            }

这段代码遍历一个键索引映射(keyIndexMap),对于每个键对应的字段列表,生成了根据这些字段组合进行查询、更新和删除的 MyBatis Mapper XML 方法定义。

  1. 遍历键索引映射 for(Map.Entry<String,List> entry:keyIndexMap.entrySet()){...}:遍历键索引映射,其中每个键对应一个字段信息列表。
  2. 生成方法名和参数名
  • 对于每个字段信息列表,遍历其中的字段信息: Integer index=0; StringBuilder methodName = new StringBuilder(); StringBuilder methodParamName = new StringBuilder();:初始化索引、方法名和方法参数名的字符串构建器。
  • 在循环中,拼接方法名和方法参数名,将属性名首字母大写后添加到方法名中,同时构建参数名形式为 “字段名 =#{属性名}”,如果不是最后一个字段,则在方法名和方法参数名中添加 “And” 或 “and” 进行连接。
  1. 查询方法定义
  • 添加注释:bw.write("\t");。
  • 定义查询方法:bw.write("\t<select id="selectBy"+ methodName+"" resultMap=""+tableInfo.getBeanName()+"ResultMap">");,指定结果映射为之前生成的结果映射。
  • 构建查询语句:bw.write("\t\tselect <include refid=""+BASE_COLUMN_LIST+""/> from "+tableInfo.getTableName()+" where "+methodParamName);,使用通用查询列和根据方法参数名构建的查询条件。
  1. 更新方法定义
  • 添加注释:bw.write("\t");。
  • 定义更新方法:bw.write("\t<update id="updateBy"+ methodName+"" parameterType=""+dtoClassName+"">");,指定参数类型为实体类全限定名。
  • 构建更新语句: bw.write("\t\t update "+tableInfo.getTableName());:指定要更新的表名。 bw.write("\t\t set");开始设置更新的字段。 遍历实体类的字段信息列表,根据字段值是否为空生成更新语句:bw.write("\t\t\t<if test="bean."+fieldInfo.getPropertyName()+"!=null">");...。 bw.write("\t\t set");结束标签。 bw.write("\t\t where "+methodParamName);:添加查询条件。
  1. 删除方法定义
  • 添加注释:bw.write("\t");。
  • 定义删除方法:bw.write("\t<delete id="deleteBy"+ methodName+"">");。
  • 构建删除语句:bw.write("\t\t delete from "+tableInfo.getTableName()+" where "+methodParamName);。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

微信图片_20241011223609.jpg