mybatis逆向工程

1,529 阅读6分钟

一:前言

使用mybatis每次自己都需要手动pojo, mapper, xml。现在借助Mybatis的逆向工程工具Mybatis Generator可以帮助我们快速完成此过程。该工具还帮助我们完成了增删改查代码的自动生成工作,大大方便了开发。

二:代码使用

添加maven依赖
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>
<dependency>
	<groupId>org.mybatis.generator</groupId>
	<artifactId>mybatis-generator-core</artifactId>
	<version>1.3.5</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.28</version>
</dependency>
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.2.3</version>
</dependency>

编写log4j的配置文件

log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

编写逆向工程的配置文件generatorConfig.xml,该配置文件参数过多,参考官网

官网:mybatis.org/generator/c…

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

    <!--配置数据库信息 -->
    <context id="DB2Tables" targetRuntime="MyBatis3">

        <!--避免生成重复代码的插件-->
        <plugin type="com.util.OverIsMergeablePlugin" />

        <!--是否在代码中显示注释-->
        <commentGenerator>
            <property name="suppressDate" value="true" />
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 ,加上“useSSL=false”是因为我SSL连接数据库出现了错误 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/day23" userId="root" password="root">
        </jdbcConnection>

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL和 NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- 指定javaBean的生成位置 -->
        <javaModelGenerator targetPackage="com.pojo" targetProject="src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="true" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!-- 指定sql映射文件生成位置 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!-- 指定dao接口的生成位置,mapper接口 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.dao" targetProject="src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        
        <!-- 选择一个table来生成相关文件,可以有一个或多个table,必须要有table元素
        选择的table会生成一下文件:
        1,SQL map文件
        2,生成一个主键类;
        3,除了BLOB和主键的其他字段的类;
        4,包含BLOB的类;
        5,一个用户生成动态查询的条件类(selectByExample, deleteByExample),可选;
        6,Mapper接口(可选)
    
        tableName(必要):要生成对象的表名;
        注意:大小写敏感问题。正常情况下,MBG会自动的去识别数据库标识符的大小写敏感度,在一般情况下,MBG会
            根据设置的schema,catalog或tablename去查询数据表,按照下面的流程:
            1,如果schema,catalog或tablename中有空格,那么设置的是什么格式,就精确的使用指定的大小写格式去查询;
            2,否则,如果数据库的标识符使用大写的,那么MBG自动把表名变成大写再查找;
            3,否则,如果数据库的标识符使用小写的,那么MBG自动把表名变成小写再查找;
            4,否则,使用指定的大小写格式查询;
        另外的,如果在创建表的时候,使用的""把数据库对象规定大小写,就算数据库标识符是使用的大写,在这种情况下也会使用给定的大小写来创建表名;
        这个时候,请设置delimitIdentifiers="true"即可保留大小写格式;
        
        可选:
        1,schema:数据库的schema;
        2,catalog:数据库的catalog;
        3,alias:为数据表设置的别名,如果设置了alias,那么生成的所有的SELECT SQL语句中,列名会变成:alias_actualColumnName
        4,domainObjectName:生成的domain类的名字,如果不设置,直接使用表名作为domain类的名字;可以设置为somepck.domainName,那么会自动把domainName类再放到somepck包里面;
        5,enableInsert(默认true):指定是否生成insert语句;
        6,enableSelectByPrimaryKey(默认true):指定是否生成按照主键查询对象的语句(就是getById或get);
        7,enableSelectByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询语句;
        8,enableUpdateByPrimaryKey(默认true):指定是否生成按照主键修改对象的语句(即update);
        9,enableDeleteByPrimaryKey(默认true):指定是否生成按照主键删除对象的语句(即delete);
        10,enableDeleteByExample(默认true):MyBatis3Simple为false,指定是否生成动态删除语句;
        11,enableCountByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询总条数语句(用于分页的总条数查询);
        12,enableUpdateByExample(默认true):MyBatis3Simple为false,指定是否生成动态修改语句(只修改对象中不为空的属性);
        13,modelType:参考context元素的defaultModelType,相当于覆盖;
        14,delimitIdentifiers:参考tableName的解释,注意,默认的delimitIdentifiers是双引号,如果类似MYSQL这样的数据库,使用的是`(反引号,那么还需要设置context的beginningDelimiter和endingDelimiter属性)
        15,delimitAllColumns:设置是否所有生成的SQL中的列名都使用标识符引起来。默认为false,delimitIdentifiers参考context的属性
        
        注意,table里面很多参数都是对javaModelGenerator,context等元素的默认属性的一个复写;
     -->

        <!-- 指定数据库表 -->
        <table tableName="province" domainObjectName="Province" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>
    </context>
</generatorConfiguration>

该逆向工程工具有一个Bug,每次重新运行代码去生成pojo、sql映射文件、mapper接口时它并不会覆盖原来的而导致重复,因此编写了一个插件利用反射去解决该问题

package com.util;

import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import java.lang.reflect.Field;
import java.util.List;

/**
 * @author admin
 * @version 1.0.0
 * @ClassName OverIsMergeablePlugin.java
 * @Description TODO 解决Mybatis逆向工程文件不覆盖的问题
 * @createTime 2020年02月06日 12:37:00
 */
public class OverIsMergeablePlugin extends PluginAdapter {

    public boolean validate(List<String> warnings) {
       return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        try {
            Field field = sqlMap.getClass().getDeclaredField("isMergeable");
            field.setAccessible(true);
            field.setBoolean(sqlMap, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}

编写运行类,一般情况下不允许运行该类,加了个时间进行限制,防止意外运行该类导致原先pojo类、mapper接口、xml映射文件上的注释被覆盖没了。

public class MybatisGenerator {

    public static void main(String[] args) throws Exception {
        String today = "2020-02-06";

        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
        Date now =sdf.parse(today);
        Date d = new Date();

        if(d.getTime()>now.getTime()+1000*60*60*24){
            System.err.println("――――――未成成功运行――――――");
            System.err.println("――――――未成成功运行――――――");
            System.err.println("本程序具有破坏作用,应该只运行一次,如果必须要再运行,需要修改today变量为今天,如:" + sdf.format(new Date()));
            return;
        }

        if(false)
            return;
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        InputStream is= MybatisGenerator.class.getClassLoader().getResource("generatorConfig.xml").openStream();
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(is);
        is.close();
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);

        System.out.println("生成代码成功,只能执行一次,以后执行会覆盖掉mapper,pojo,xml 等文件上做的修改");

    }
}

三:相关链接

mybatis逆向工程配置详细说明:blog.csdn.net/xlx1992/art…
逆向工程生成后的mapper接口使用 blog.csdn.net/biandous/ar…