资讯专栏INFORMATION COLUMN

Mybatis自动代码生成器的实现

monw3c / 2448人阅读

摘要:原博地址本文介绍如何用编写高度自定义的代码生成器是一款优秀的持久层框架,它支持定制化存储过程以及高级映射。避免了几乎所有的代码和手动设置参数以及获取结果集。

原博地址https://laboo.top/2018/11/26/a-db/#more

本文介绍如何用Java编写高度自定义的代码生成器

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息。

上面这一段话来自Mybatis官网的介绍, 初用Mybatis时感觉这个框架相比于JDBC优雅多了, 用起来也如官网说的非常简单。但是用了一段时间之后, 弊端就慢慢凸显出来了

使用Mybatis时不得不为每个表创建一个Entity.javaMapper.xml(Mapper可以融合入Dao中)Dao.java,Service.java 层次很清晰, 但是太多重复性的工作了, 费时间且易于出错

并且当数据库发生一点改动的时候... 苦不堪言

后来出现了自动生成代码的插件, 但是总是不尽人意, 不能随心所欲地控制, 毕竟每个人的需求都不一样

本文就来介绍如何简单的编写一个自己的代码生成器

项目源码

mybatis-generator

代码实现

实现的思路很简单, 首先查询数据库的表结构, 得到列名, 列类型...等信息

创建文件模版, 将这些信息插入模版中, 最后打包模版进压缩包导出

代码实现 一共五个Java类

TableDO

ColumnDO

GeneratorMapper

GeneratorUtils

GeneratorService

首先来看两个实体类

TableDO 和 ColumnDO

TableDO 存放表名, 对于的类名, 以及列信息

完整类代码 TableDO.java

public class TableDO {

    private String tableName;
    private List columns;
    private String className;
    private String suffix;

    // get()... set()...
}

ColumnDO 存放列名, 数据库字段类型, 以及对应Java中的属性名和类型

完整类代码 ColumnDO.java

public class ColumnDO {

    private String columnName;
    private String dataType;
    private String attrName;
    private String attrLowerName;
    private String attrType;

    // get()... set()...
}
GeneratorMapper

在GeneratorMapper 中, 我们通过表名查询表自动的信息

完整类代码 GeneratorMapper.java

@Mapper
public interface GeneratorMapper {

    @Select("select column_name columnName, data_type dataType from information_schema.columns where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position")
    List listColumns(String tableName);
}
GeneratorUtils

在GeneratorUtils 中进行类信息与模版之间的转换

完整类代码 GeneratorUtils.java

将表信息放入Velocity模版的上下文中

Map map = new HashMap<>();
map.put("tableName", table.getTableName());
map.put("className", table.getClassName());
map.put("pathName", getPackageName().substring(getPackageName().lastIndexOf(".") + 1));
map.put("columns", table.getColumns());
map.put("package", getPackageName());
map.put("suffix", table.getSuffix());

Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
VelocityContext context = new VelocityContext(map);

添加模版

List templates = new ArrayList<>();
templates.add("mybatis/Model.java.vm");
templates.add("mybatis/Query.java.vm");
templates.add("mybatis/Dao.java.vm");
templates.add("mybatis/Mapper.xml.vm");
templates.add("mybatis/Service.java.vm");

编译模版

StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, sw);

Utils类完成了生成代码的主要工作, 但是代码也是比较简单的

GeneratorService

在Service 中注入Mapper 查询列信息, 并用Utils生成代码, 然后导出压缩包

完整类代码 GeneratorService.java

@Service
public class GeneratorService {

    @Resource
    private GeneratorMapper generatorMapper;

    @Resource
    private Environment environment;

    public void generateZip(String[] tableNames, String zipPath) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (String tableName : tableNames) {
            TableDO table = new TableDO();
            table.setTableName(tableName);
            table.setColumns(generatorMapper.listColumns(tableName));
            GeneratorUtils.generatorCode(table, zip,getConfig());
        }
        IOUtils.closeQuietly(zip);
        FileOutputStream file = new FileOutputStream(zipPath);
        file.write(outputStream.toByteArray());
        file.close();
    }

    // getConfig ...
}
VM模版

自己写代码生成器的好处就是, 可以根据需求定制自己的模版, 下面是我的几个模版可以供参考

Mapper.xml.vm

Dao.java.vm

Service.java.vm

Model.java.vm

Query.java.vm

生成的代码是在commons-mybatis架构下使用的

Dao.java.vm
package ${package}.database.dao;

import ${package}.database.model.${className}${suffix};

import org.apache.ibatis.annotations.Mapper;
import org.laziji.commons.mybatis.dao.${suffix}Dao;

@Mapper
public interface ${className}Dao extends ${suffix}Dao<${className}${suffix}> {

}
...

其余模版

使用 配置文件

resources下创建application-${name}.yml文件, ${name}随意, 例如: application-example.yml, 可创建多个

配置文件内容如下, 填入数据库配置, 以及生成代码的包名, 源文件路径

spring:
  datasource:
    url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/xxxx?characterEncoding=utf-8
    username: xxxxxx
    password: xxxxxx

generator:
  package: com.xxx.xxx
  resources: mapper
Test

在test文件下创建测试类

@ActiveProfiles("example")中填入刚才配置文件名的name

tableNames需要生成的表, 可以多个

zipPath 代码导出路径

运行测试方法即可

package pg.laziji.generator;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import pg.laziji.generator.mybatis.GeneratorService;

import javax.annotation.Resource;
import java.io.IOException;

@ActiveProfiles("example")
@RunWith(SpringRunner.class)
@SpringBootTest
public class ExampleTest {

    @Resource
    private GeneratorService generatorService;

    @Test
    public void test() throws IOException {
        String[] tableNames = new String[]{"example_table1", "example_table2"};
        String zipPath = "/home/code.zip";
        generatorService.generateZip(tableNames,zipPath);
    }
}
欢迎关注我的博客公众号

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72444.html

相关文章

  • 【效率专精系列】善用插件提升MyBatis开发效率

    摘要:通过插件更优雅地生成和的样板代码通过插件不污染地实现优雅分页。使用步骤引入依赖,在或的配置中进行配置。提供语法提示自动补全错误提示导航功能。该插件提供了类似的功能,根据接口的方法名推断含义,然后在中直接生成对应的。 团队使用Mybatis作为数据库访问框架。不同于Hibernate这种采用经典面向对象思想设计的ORM框架,Mybatis是面向过程的,它只做了过程到SQL语句的映射。两者...

    Kylin_Mountain 评论0 收藏0
  • Mybatis【逆向工程,缓存,代理】知识要点

    摘要:一级缓存值得注意的地方默认就是支持一级缓存的,并不需要我们配置和整合后进行代理开发,不支持一级缓存,和整合,按照的模板去生成代理对象,模板中在最后统一关闭。总结的一级缓存是级别的。 前言 本文主要讲解Mybatis的以下知识点: Mybatis缓存 一级缓存 二级缓存 与Ehcache整合 Mapper代理 使用Mapper代理就不用写实现类了 逆向工程 自动生成代码 ...

    wanglu1209 评论0 收藏0
  • MyBatis-Plus初步

    摘要:是最流行的关系型数据库管理系统之一,在应用方面,是最好的,关系数据库管理系统应用软件。是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。 本章主要是对MyBatis-Plus的初步介绍,包括一些背景知识、环境搭建、初步使用等知识和例子。对于背景知识,主要包含对MyBatis-Plus的特性介绍、为什么使用MyB...

    娣辩孩 评论0 收藏0
  • 面试官都会问Mybatis面试题,你会这样回答吗?

    摘要:最终能和面试官聊的开心愉快投缘的叫面霸。能够与很好的集成提供映射标签,支持对象与数据库的字段关系映射提供对象关系映射标签,支持对象关系组件维护。使用可以有效的防止注入,提高系统安全性。 showImg(https://segmentfault.com/img/bVbsSlt?w=358&h=269); 一、概述 面试,难还是不难?取决于面试者的底蕴(气场+技能)、心态和认知及沟通技巧。...

    seanHai 评论0 收藏0
  • MyBatis知识点整理

    摘要:得到用户信息,将用户信息存储到一级缓存中。如果中间去执行操作执行插入更新删除,则会清空中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。 基础: 1、 概念:Java当中的一个持久层框架。2、 特点、优势:(1)把java代码和SQL代码做了一个完全分离。(2)良好支持复杂对象的映射(输入映射、输出映射)(3)使用动态SQL,可以预防SQL注入。3、 ...

    zhangqh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<