1. 程式人生 > >自定義Mybatis逆向工程Maven外掛

自定義Mybatis逆向工程Maven外掛

我的一篇部落格介紹了基於Java Config形式的Mybatis逆向工程,通過定義幾個java變數,然後執行main方法可以執行逆向工程,這篇部落格就是將那個工程改造成一個Maven外掛。

開發Maven外掛,首先需要建立一個Maven Plugin專案,我是基於IDEA開發的。IDEA如何建立Maven外掛專案自行百度,這裡就不說了。
建立好Mojo專案後,需要修改器Pom.xml檔案,指定packaging型別為maven-plugin,同時新增開發外掛的依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns
="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.bob</groupId> <artifactId>
plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <properties> <maven.version>3.5.2</maven.version> <plugin-annotations.version>3.3</plugin-annotations.version> <mybatis-generator
>
1.3.5</mybatis-generator> </properties> <dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>${maven.version}</version> </dependency> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>${plugin-annotations.version}</version> </dependency> <!-- Mybatis 逆向工程 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>${mybatis-generator}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>

@Mojo():定義外掛目標,一個外掛可以有多個目標,也就是有 多個@Mojo標識的AbstractMojo子類,繫結外掛時可以自由選擇將哪個目標繫結到Maven生命週期的某個階段。

下一步你需要有一個類去繼承AbstractMojo,重寫其execute方法,外掛在執行時會呼叫此方法,也就是說此方法是外掛的入口。外掛在啟動時會例項化一個AbstractMojo的子類,具體例項化誰需要看@Mojo註解在哪層子類上,所以此處我定義了兩個類直接或間接繼承AbstractMojo,MybatisGeneratorConfig作為配置類,MybatisGenerator是實際執行逆向工程的工具類,MybatisGenerator 繼承MybatisGeneratorConfig,將@Mojo標識在MybatisGenerator上。這樣MybatisGenerator在執行execute方法時能夠獲取到MybatisGeneratorConfig裡的配置資訊。

/**
 * Mybatis逆向工程解析器
 * 基於Mybatis Generator 1.3.5 Release
 *
 * @author wb-jjb318191
 * @create 2017-09-28 17:08
 */
public abstract class MybatisGenerator extends AbstractMojo {

    /**
     * 指定要生成的Table
     */
    @Parameter(required = true)
    protected List<String> tables;

    /**
     * 連線資料庫驅動包,預設地址字首是"targetModule"模組下的resources路徑
     */
    @Parameter(defaultValue = "mysql-connector-java-5.1.44-bin.jar")
    protected String driverPath;

    /**
     * 指定生成java檔案的編碼格式
     */
    @Parameter(defaultValue = "UTF-8")
    protected String fileEncoding;

    /**
     * 指定JDBC資訊
     */
    @Parameter(defaultValue = "com.mysql.jdbc.Driver")
    protected String driverClass;

    /**
     * 指定連線資料庫的地址
     */
    @Parameter(defaultValue = "jdbc:mysql://localhost:3306/project")
    protected String connectionUrl;

    /**
     * 使用者名稱
     */
    @Parameter(defaultValue = "root")
    protected String userName;

    /**
     * 密碼
     */
    @Parameter(defaultValue = "lanboal")
    protected String password;

    /**
     * 指定專案根目錄
     */
    @Parameter(property = "user.dir")
    private String projectRootPath;

    /**
     * 指定檔案生成的模組
     */
    @Parameter(defaultValue = "")
    private String targetModule;

    /**
     * java根路徑
     */
    @Parameter(defaultValue = "\\src\\main\\java")
    private String javaPath;

    /**
     * 資源根路徑
     */
    @Parameter(defaultValue = "\\src\\main\\resources")
    private String resuorcesPath;

    /**
     * 指定Java Model生成位置
     */
    protected String javaModelTargetProject;

    /**
     * java實體類包名
     */
    @Parameter(defaultValue = "com.bob.project.mvc.entity.model")
    protected String javaModelPackage;

    /**
     * 指定Java DAO介面生成位置
     */
    protected String javaMapperTargetProject;

    /**
     * Mapper介面包名
     */
    @Parameter(defaultValue = "com.bob.project.mvc.mapper")
    protected String javaMapperPackage;

    /**
     * 指定Mapper.xml生成位置
     */
    protected String sqlmapTargetproject;

    /**
     * Mapper.xml檔案路徑
     */
    @Parameter(defaultValue = "com.bob.project.mvc.mapper", required = false)
    protected String sqlMapperPackage;

    /**
     * 初始化引數
     */
    protected void initParameter() {
        if (!"".equals(targetModule)) {
            targetModule = "\\" + targetModule;
        }
        String pathPrefix = projectRootPath + targetModule;
        javaModelTargetProject = pathPrefix + javaPath;
        javaMapperTargetProject = pathPrefix + javaPath;
        sqlmapTargetproject = pathPrefix + resuorcesPath;
        //獲取驅動Jar包的路徑,若不是本地地址,則加上專案字首
        if (!driverPath.contains(":")) {
            driverPath = sqlmapTargetproject + "\\" + driverPath;
        }
    }

    protected void printParameters() {
        System.out.println("列印逆向工程列印引數");
        System.out.println("tables :" + tables.toString());
        System.out.println("fileEncoding :" + fileEncoding.toString());
        System.out.println("driverPath :" + driverPath.toString());
        System.out.println("driverClass :" + driverClass.toString());
        System.out.println("connectionUrl :" + connectionUrl.toString());
        System.out.println("userName :" + userName.toString());
        System.out.println("password :" + password.toString());
        System.out.println("targetModule :" + targetModule.toString());
        System.out.println("projectRootPath :" + projectRootPath.toString());
        System.out.println("javaModelTargetProject :" + javaModelTargetProject.toString());
        System.out.println("javaMapperTargetProject :" + javaMapperTargetProject.toString());
        System.out.println("sqlmapTargetproject :" + sqlmapTargetproject.toString());
    }

}

/**
 * Mybatis逆向工程基於Java形式的配置類
 *
 * @author wb-jjb318191
 * @create 2017-09-30 9:17
 */
@Mojo(name = "mybatisGenerate")
public class MybatisGenerator extends MybatisGeneratorConfig {

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        initParameter();
        printParameters();
        try {
            Configuration config = configMybatisGenerator();
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, new DefaultShellCallback(true), new ArrayList<String>());
            myBatisGenerator.generate(null);
        } catch (Exception e) {
            System.out.println("逆向工程執行失敗");
            e.printStackTrace();
        }
    }

    public Configuration configMybatisGenerator() {
        Configuration configuration = new Configuration();
        configuration.addClasspathEntry(driverPath);
        Context context = new Context(null);
        context.setTargetRuntime("MyBatis3");
        context.setId("wb-jjb318191");
        context.addProperty("javaFileEncoding", fileEncoding);
        //設定註解生成器
        context.setCommentGeneratorConfiguration(generateCommentConfiguration());
        //設定JDBC連線配置
        context.setJdbcConnectionConfiguration(generateJDBCConnectionConfiguration());
        //設定JDBC Type 與Java Type之間的對映解析器
        context.setJavaTypeResolverConfiguration(generateJavaTypeResolverConfiguration());
        //設定Java Model生成配置
        context.setJavaModelGeneratorConfiguration(generateJavaModelGeneratorConfiguration());
        //設定DAO層的生成配置
        context.setSqlMapGeneratorConfiguration(generateSqlMapGeneratorConfiguration());
        //設定Mapper.xml生成
        context.setJavaClientGeneratorConfiguration(generateJavaClientGeneratorConfiguration());
        //設定需要生成的Table及生成形式
        for (TableConfiguration tableConfiguration : generateTableConfigurations(context)) {
            context.addTableConfiguration(tableConfiguration);
        }
        configuration.addContext(context);
        return configuration;
    }

    /**
     * 配置註解生成器
     *
     * @return
     */
    private CommentGeneratorConfiguration generateCommentConfiguration() {
        CommentGeneratorConfiguration configuration = new CommentGeneratorConfiguration();
        configuration.setConfigurationType(GeneralCommentGenerator.class.getName());
        //是否去除自動生成的註釋 true:是 : false:否
        configuration.addProperty("suppressAllComments", "false");
        configuration.addProperty("addRemarkComments", "true");
        return configuration;
    }

    /**
     * 設定資料庫連線的資訊:驅動類、連線地址、使用者名稱、密碼
     *
     * @return
     */
    private JDBCConnectionConfiguration generateJDBCConnectionConfiguration() {
        JDBCConnectionConfiguration configuration = new JDBCConnectionConfiguration();
        configuration.setDriverClass(driverClass);
        String jdbcSuffix = "?useUnicode=true&characterEncoding=UTF8&useSSL=false";
        configuration.setConnectionURL(connectionUrl + jdbcSuffix);
        configuration.setUserId(userName);
        configuration.setPassword(password);
        return configuration;
    }

    /**
     * 設定JDBC Type 與Java Type之間的對映解析器
     *
     * @return
     */
    private JavaTypeResolverConfiguration generateJavaTypeResolverConfiguration() {
        JavaTypeResolverConfiguration configuration = new JavaTypeResolverConfiguration();
        //可自定義型別對映解析器
        configuration.setConfigurationType(null);
        //預設false,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer,為 true時把JDBC DECIMAL 和 NUMERIC 型別解析為java.math.BigDecimal
        configuration.addProperty("forceBigDecimals", "true");
        return configuration;
    }

    /**
     * 配置Java Model生成
     *
     * @return
     */
    private JavaModelGeneratorConfiguration generateJavaModelGeneratorConfiguration() {
        JavaModelGeneratorConfiguration configuration = new JavaModelGeneratorConfiguration();
        configuration.setTargetProject(javaModelTargetProject);
        configuration.setTargetPackage(javaModelPackage);
        //是否讓schema作為包的字尾
        configuration.addProperty("enableSubPackages", "false");
        //從資料庫返回的值被清理前後的空格
        configuration.addProperty("trimStrings", "true");
        return configuration;
    }

    /**
     * 配置Mapper.xml生成
     *
     * @return
     */
    private SqlMapGeneratorConfiguration generateSqlMapGeneratorConfiguration() {
        SqlMapGeneratorConfiguration configuration = new SqlMapGeneratorConfiguration();
        configuration.setTargetProject(sqlmapTargetproject);
        configuration.setTargetPackage(sqlMapperPackage);
        //是否讓schema作為包的字尾
        configuration.addProperty("enableSubPackages", "false");
        return configuration;
    }

    /**
     * 設定DAO生成
     *
     * @return
     */
    private JavaClientGeneratorConfiguration generateJavaClientGeneratorConfiguration() {
        JavaClientGeneratorConfiguration configuration = new JavaClientGeneratorConfiguration();
        configuration.setConfigurationType("XMLMAPPER");
        configuration.setTargetProject(javaMapperTargetProject);
        configuration.setTargetPackage(javaMapperPackage);
        //是否讓schema作為包的字尾
        configuration.addProperty("enableSubPackages", "false");
        return configuration;
    }

    private List<TableConfiguration> generateTableConfigurations(Context context) {
        List<TableConfiguration> configurations = new ArrayList<TableConfiguration>();
        for (Object table : tables) {
            TableConfiguration configuration = new TableConfiguration(context);
            configuration.setTableName((String)table);
            configuration.setSelectByExampleStatementEnabled(false);
            configuration.setDeleteByExampleStatementEnabled(false);
            configuration.setCountByExampleStatementEnabled(false);
            configuration.setUpdateByExampleStatementEnabled(false);
            configurations.add(configuration);
        }
        return configurations;
    }

}

還有一個類GeneralCommentGenerator和之前那篇部落格的一樣,就不列出來了,總共就是三個類。

我在MybatisGeneratorConfig類裡的變數上標識了很多@Parameter註解,這些註解指定了外掛在配置時能夠傳入哪些外部引數,Maven外掛在啟動時例項化@Mojo標識類的物件,同時將外部引數傳入到此類(或父類)的屬性中。@Parameter可以定義外掛配置的形式,是否有預設值,是否僅可讀,是否必須等等,若是必須的則在配置外掛時必須有值。

以上就是外掛的所有程式碼了,之後執行Maven的install命令,將外掛安裝到本地maven倉庫。

下面就是在其他專案中使用整個外掛。

首先需要在專案中引入自定義的maven外掛:

        <plugins>
            <!--############## Maven依賴外掛 ############## -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.0.2</version>
            </plugin>

            <plugin>
                <groupId>com.bob</groupId>
                <artifactId>plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
                <configuration>
                    <tables>
                        <table>bank_account</table>
                        <table>emp</table>
                    </tables>
                    <targetModule>project-root</targetModule>
                </configuration>
                <executions>
                    <execution>
                        <id>generate</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>mybatisGenerate</goal>  <!--執行完之後註釋掉 -->
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

我預設是在一臺電腦上,剛剛已經將外掛安裝到了本地maven倉庫,所以這裡引用能夠直接生效。
可以通過Ctrl+左鍵點選configuration內的配置,檢視當前外掛的可配置選項。
我們將逆向工程外掛的mybatisGenerate目標繫結到了compile階段,也就是說在執行maven compile生命週期時會觸發此外掛的相應目標。
這裡寫圖片描述
外掛配置在了project目錄下的pom.xml裡,逆向工程的資料庫驅動包放在了project-root下,同時制定生成的Model,Mapper介面及Mapper.xml也指向project-root專案。生成的包的路徑,資料庫地址,使用者名稱,密碼等等資訊我在外掛裡做了預設配置,需要的可以在< configuration>覆蓋預設配置,同時若專案的結構和我的不相同,只要修改下外掛裡的預設配置就好了。自行看外掛原始碼,很明瞭的。

在指定好要生成的資料庫表之後,在IDEA裡執行complie,就能執行逆向工程外掛了,執行完之後務必將< goal>,否則每次編譯都會執行此外掛了。