手写简易的MyBatis代码自动生成器,适配自己的项目,再也不用重复造轮子了

41 阅读5分钟

目录

切记!本博客只是提供一个思路,具体模板内容需要自己动手写,因为每个公司每个项目的框架可能稍有差异

写在前面

生成原理

正常Controller、Service、Dao的生成

模板实例

数据库表名转换成蛇形bean名称

bean名称首字母变大写

读取txt文件

写入文件

domain的生成

domain的模板

获取表结构

拼接domain的字段和getSet方法

mapper.xml的生成

mapper.xml的模板

mapper.xml数据拼接


切记!本博客只是提供一个思路,具体模板内容需要自己动手写,因为每个公司每个项目的框架可能稍有差异

写在前面

众所周知,MyBatis的xml配置以及domain实体类等等,重复的工作量非常大。很多小伙伴从网上找的自动生成代码的工具,生成的都跟自己实际项目中的不太一样,还要进行改造。

所以,我们可以手写一个适应项目中的增删改查一套模板,然后在此基础上进行开发,大大的减少了重复造轮子的时间。

生成原理

原理非常简单,将一些差异性的东西,使用占位符{xxxx}代替,然后读取模板文件,使用全局字符串替换即可。

例如domain模板文件

{copyright}

package com.cxf.domain.{packageName};

/**
 * {tbChineseName}
 *
 * @author {user}
 * @since {date}
 */
public class {upperBeanName} {

{domainFields}

{domainGetset}
}

生成的时候,只需要读取模板之后,使用String text = text.replace("{user}", user);即可将{user}里面的东西一键替换。

正常Controller、Service、Dao的生成

这几个很简单,基本就靠表名,替换一下类名就可以了。

模板实例

@RestController
@RequestMapping("/{beanParamName}s")
public class {controllerName} {

    @Autowired
    private {daoName} {daoParamName};

    @PostMapping
    @ApiOperation(value = "保存")
    public {beanName} save(@RequestBody {beanName} {beanParamName}) {
        {daoParamName}.save({beanParamName});

        return {beanParamName};
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "根据id获取")
    public {beanName} get(@PathVariable Long id) {
        return {daoParamName}.getById(id);
    }

    @PutMapping
    @ApiOperation(value = "修改")
    public {beanName} update(@RequestBody {beanName} {beanParamName}) {
        {daoParamName}.update({beanParamName});

        return {beanParamName};
    }

    @GetMapping
    @ApiOperation(value = "列表")
    public PageTableResponse list(PageTableRequest request) {
        return new PageTableHandler(new CountHandler() {

            @Override
            public int count(PageTableRequest request) {
                return {daoParamName}.count(request.getParams());
            }
        }, new ListHandler() {

            @Override
            public List<{beanName}> list(PageTableRequest request) {
                return {daoParamName}.list(request.getParams(), request.getOffset(), request.getLimit());
            }
        }).handle(request);
    }

    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除")
    public void delete(@PathVariable Long id) {
        {daoParamName}.delete(id);
    }
}
@Mapper
public interface {daoName} {

    @Select("select * from {table_name} t where t.id = #{id}")
    {beanName} getById(Long id);

    @Delete("delete from {table_name} where id = #{id}")
    int delete(Long id);

    int update({beanName} {beanParamName});
    
    int save({beanName} {beanParamName});
    
    int count(@Param("params") Map<String, Object> params);

    List<{beanName}> list(@Param("params") Map<String, Object> params, @Param("offset") Integer offset, @Param("limit") Integer limit);
}

数据库表名转换成蛇形bean名称

String beanName = separated2Camel("t_user" , '_');

public static String separated2Camel(String name, char separator) {
        if (StringUtils.isBlank(name)) {
            return null;
        }
        name = StringUtils.lowerCase(name);
        // 去掉开头的
        while (StringUtils.startsWith(name, String.valueOf(separator))) {
            name = StringUtils.substring(name, 1);
        }
        // 去掉最后的
        while (StringUtils.endsWith(name, String.valueOf(separator))) {
            name = StringUtils.substring(name, 0, name.length() - 1);
        }

        // 去掉中间的,后面首字母大写
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (c == separator) {
                i++;
                sb.append(Character.toUpperCase(name.charAt(i)));
                continue;
            }
            sb.append(c);
        }

        return sb.toString();
    }

bean名称首字母变大写

    /**
     * 首字母变大写
     */
    public static String firstCharToUpper(String name){
        if(StringUtils.isEmpty(name)){
            return name;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(Character.toUpperCase(name.charAt(0)));
        sb.append(name.substring(1));
        return sb.toString();
    }

读取txt文件

    /**
     * 读入文件
     */
    public static String getText(String path)
    {
        String filecontent = "";
        try {
            File f = new File(path);
            if (f.exists()) {
                FileReader fr = new FileReader(path);
                BufferedReader br = new BufferedReader(fr); //建立BufferedReader对象,并实例化为br
                String line = br.readLine(); //从文件读取一行字符串
                //判断读取到的字符串是否不为空
                while (line != null) {
                    filecontent += line + "\n";
                    line = br.readLine(); //从文件中继续读取一行数据
                }
                br.close(); //关闭BufferedReader对象
                fr.close(); //关闭文件
            }

        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return filecontent;
    }

写入文件

    /**
     * 将文本写入文件
     *
     * @param value
     * @param path
     */
    public static void saveTextFile(String value, String path) {
        FileWriter writer = null;
        try {
            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            writer = new FileWriter(file);
            writer.write(value);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

domain的生成

domain的模板

public class {upperBeanName} {

{domainFields}

{domainGetset}
}

获取表结构

    public static List<Map<String, Object>> getTbInfo(Connection conn, String dBschema, String tbName) {
        String sql = "SELECT " +
                "    C.TABLE_SCHEMA AS 'km', " + //库名
                "    T.TABLE_NAME AS 'bm', " + //表名
                "    T.TABLE_COMMENT AS 'bzs', " + //表注释
                "    C.COLUMN_NAME AS 'lm', " + //列名
                "    C.COLUMN_COMMENT AS 'lzs', " + //列注释
                "    C.ORDINAL_POSITION AS 'ldplsx', " + //列的排列顺序
                "    C.COLUMN_DEFAULT AS 'mrz', " + //默认值
                "    C.IS_NULLABLE AS 'sfwk', " + //是否为空
                "    C.DATA_TYPE AS 'sjlx', " + //数据类型
                "    C.CHARACTER_MAXIMUM_LENGTH AS 'zfzdcd', " + //字符最大长度
                "    C.NUMERIC_PRECISION AS 'szjd', " + //数值精度(最大位数)
                "    C.NUMERIC_SCALE AS 'xsjd', " + //小数精度
                "    C.COLUMN_TYPE AS 'llx', " + //列类型
                "    C.COLUMN_KEY 'key', " + //KEY
                "    C.EXTRA AS 'ewsm' " + //额外说明
                " FROM " +
                "    information_schema.`TABLES` T " +
                " LEFT JOIN information_schema.`COLUMNS` C ON T.TABLE_NAME = C.TABLE_NAME " +
                " AND T.TABLE_SCHEMA = C.TABLE_SCHEMA " +
                " WHERE " +
                "    T.TABLE_SCHEMA = ?  AND " +
                "    T.TABLE_NAME = ?" +
                " ORDER BY " +
                "    C.TABLE_NAME, " +
                "    C.ORDINAL_POSITION";
        System.out.println("执行sql:" + sql);
        List<Object> list = new ArrayList<Object>();
        list.add(dBschema);
        list.add(tbName);
        try {
            return executeQuery(conn, sql, list);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static List<Map<String, Object>> executeQuery(Connection conn, String sql, List<Object> parameters)
            throws SQLException {
        List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();

        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);

            setParameters(stmt, parameters);

            rs = stmt.executeQuery();

            ResultSetMetaData rsMeta = rs.getMetaData();

            while (rs.next()) {
                Map<String, Object> row = new LinkedHashMap<String, Object>();

                for (int i = 0, size = rsMeta.getColumnCount(); i < size; ++i) {
                    String columName = rsMeta.getColumnLabel(i + 1);
                    Object value = rs.getObject(i + 1);
                    row.put(columName, value);
                }

                rows.add(row);
            }
        } finally {
            JdbcUtils.close(rs);
            JdbcUtils.close(stmt);
        }

        return rows;
    }

拼接domain的字段和getSet方法

    private static void getDomainVal() {
        StringBuilder fieldsSb = new StringBuilder();
        StringBuilder getsetSb = new StringBuilder();
        for (Map<String, Object> fields : tbInfo) {
            if(fields.get("lm").equals("create_by") || fields.get("lm").equals("create_at") || fields.get("lm").equals("update_by") || fields.get("lm").equals("update_at")){
                continue;
            }
            String type = getFieldType(fields.get("sjlx").toString());
            String name = separated2Camel(fields.get("lm").toString(), '_');
            // 拼接字段
            fieldsSb.append("\t// ").append(fields.get("lzs")).append("\n");
            fieldsSb.append("\tprivate ").append(type).append(" ").append(name).append(";\n");
            // 拼getset
            getsetSb.append("\tpublic ").append(type).append(" get")
                    .append(firstCharToUpper(name))
                    .append("() {\n");
            getsetSb.append("\t\treturn ").append(name).append(";\n");
            getsetSb.append("\t}\n");
            getsetSb.append("\tpublic void set")
                    .append(firstCharToUpper(name))
                    .append("(").append(type).append(" ").append(name).append(") {\n");
            getsetSb.append("\t\tthis.").append(name).append(" = ").append(name).append(";\n");
            getsetSb.append("\t}\n");
        }
        domainFields = fieldsSb.toString();
        domainGetset = getsetSb.toString();
    }

mapper.xml的生成

mapper.xml的模板

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cxf.mapper.{packageName}.{upperBeanName}Mapper">
  <resultMap id="{upperBeanName}Map" type="com.cxf.model.{packageName}.{upperBeanName}Model">
{resultMap}
  </resultMap>

  <sql id="sqlAllColumns">
{sqlAllColumns}
  </sql>

  <sql id="where">
    <where>
{selectWhere}
    </where>
  </sql>

  <select id="selectById" resultMap="{upperBeanName}Map">
    SELECT
    <include refid="sqlAllColumns"/>
    FROM `{tbName}`
    where `id`=#{id}
  </select>

  <select id="selectOne" resultMap="{upperBeanName}Map">
    SELECT
{sqlAllColumnst}
    FROM `{tbName}` t
    LIMIT 1
  </select>

  <select id="selectAll" resultMap="{upperBeanName}Map">
    SELECT
    <include refid="sqlAllColumns"/>
    FROM `{tbName}`
    <where>
      <if test="id != null and id != ''">
        and id = #{id}
      </if>
    </where>
  </select>

  <insert id="insert">
    insert into `{tbName}` ( <include refid="sqlAllColumns"/>)
    values ({insertVal})
  </insert>

  <update id="update">
    update `{tbName}`
    set
{updateVal}
    WHERE `id` = #{id}
  </update>

  <update id="patch">
    update `{tbName}`
    <set>
{updateSet}
    </set>
    where `id` = #{id}
  </update>

  <delete id="delete">
        DELETE
        FROM `{tbName}`
        WHERE `id` = #{0}
  </delete>

</mapper>

mapper.xml数据拼接


    private static void getXmlVal() {
        StringBuilder sqlAllColumnsSb = new StringBuilder();    sqlAllColumnsSb.append("\t");
        StringBuilder resultMapSb = new StringBuilder();
        StringBuilder sqlAllColumnstSb = new StringBuilder();    sqlAllColumnstSb.append("\t\t");
        StringBuilder selectWhereSb = new StringBuilder();
        StringBuilder insertValSb = new StringBuilder();
        StringBuilder updateSetSb = new StringBuilder();
        StringBuilder updateValSb = new StringBuilder();
        for (int i = 0; i < tbInfo.size(); i++) {
            Map<String, Object> fields = tbInfo.get(i);
            String name = fields.get("lm").toString();
            // 拼接sqlAllColumns
            if(i != 0 && i%8 == 0){
                sqlAllColumnsSb.append("\n\t");
            }
            sqlAllColumnsSb.append("`").append(name).append("`");
            if(tbInfo.size() != i +1){
                sqlAllColumnsSb.append(",");
            }
            // 拼接resultMapSb
            resultMapSb.append("\t").append("<");
            if(name.equals("id")){
                resultMapSb.append("id ");
            } else {
                resultMapSb.append("result ");
            }
            resultMapSb.append("column=\"").append(name).append("\" property=\"").append(separated2Camel(name, '_')).append("\" />");
            if(tbInfo.size() != i +1){
                resultMapSb.append("\n");
            }
            // 拼接带别名的表字段
            if(i != 0 && i%8 == 0){
                sqlAllColumnstSb.append("\n\t\t");
            }
            sqlAllColumnstSb.append("t.`").append(name).append("`");
            if(tbInfo.size() != i +1){
                sqlAllColumnstSb.append(",");
            }
            // 拼接where条件
            selectWhereSb.append("\t\t<if test=\"" + separated2Camel(name, '_') + " != null and " + separated2Camel(name, '_') + " != ''\">\n");
            selectWhereSb.append("\t\t\tand `" + name).append("` = ").append("#{").append(separated2Camel(name, '_'))
                    .append("} \n");
            selectWhereSb.append("\t\t</if>");
            if(tbInfo.size() != i +1){
                selectWhereSb.append("\n");
            }
            // 拼接insert字段
            if(i != 0 && i%8 == 0){
                insertValSb.append("\n\t\t");
            }
            insertValSb.append("#{").append(separated2Camel(name, '_')).append("}");
            if(tbInfo.size() != i +1){
                insertValSb.append(", ");
            }
            // 拼接update字段
            if (!"id".equals(name)) {
                updateSetSb.append("\t\t<if test=\"" + separated2Camel(name, '_') + " != null\">\n");
                updateSetSb.append("\t\t\t`" + name).append("` = ").append("#{").append(separated2Camel(name, '_') )
                        .append("}, \n");
                updateSetSb.append("\t\t</if>");
                if(tbInfo.size() != i +1){
                    updateSetSb.append("\n");
                }
            }
            // 拼接直接update字段
            if (!"id".equals(name)) {
                updateValSb.append("\t\t`" + name).append("` = ").append("#{").append(separated2Camel(name, '_') )
                        .append("}");
                if(tbInfo.size() != i +1){
                    updateValSb.append(", \n");
                }
            }

        }
        sqlAllColumns = sqlAllColumnsSb.toString();
        resultMap = resultMapSb.toString();
        sqlAllColumnst = sqlAllColumnstSb.toString();
        selectWhere = selectWhereSb.toString();
        insertVal = insertValSb.toString();
        updateSet = updateSetSb.toString();
        updateVal = updateValSb.toString();
    }