mybatis_generator合并xml mapper文件

一.问题

用的mybatis.generator 1.3.6版本,版本没啥大关系.

目前的xml输出有两个主要的问题:

1.xml追加而不是覆盖

这样就导致一个xml mapper文件每个node都重复,肯定不行.

2.即使可以覆盖,如果需要对mapper增删改呢?

假如你数据库没配置外键,第一遍生成mapper肯定要手动加关联.

关联加好了,如果后期数据库加了几个字段,或者忘了给insert用

 <generatedKey column="id" sqlStatement="MySql"/>

配置数据库自动生成主键.

数据库有二三十张表,挨个改不仅效率慢,而且容易出错或者漏掉.

但是因为改了mapper,重新生成就会覆盖(前面的1完成的),即使不覆盖追加,也要挨个删挨个合并.

二.需求

增加一个<sql>,但是合并的时候要求保留

删除自动生成的某些<sql>,其实这个没啥意义,如果非要删除在配置文件中

参考:http://blog.csdn.net/testcs_dn/article/details/77881776

因为数据库没有外键

配置关联关系,几乎全部的<sql>都要改.

但是重新生成时不要覆盖掉.

三.解决方案

package com.haitian.plugins;

import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.api.dom.xml.Element;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User:zhangweixiao
 * Description:
 */
public class NoDoubleNodes extends PluginAdapter {

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

    //mybatis_generator中类,用来根据TargetProject和TargetPackage生成File,自己写也不难.
    ShellCallback shellCallback=new DefaultShellCallback(false);
    //因为sqlMapDocumentGenerated先调用,要保存Document,用来在sqlMapGenerated中删除子node
    org.mybatis.generator.api.dom.xml.Document document;

    @Override
    public boolean sqlMapDocumentGenerated(org.mybatis.generator.api.dom.xml.Document document,
                                           IntrospectedTable introspectedTable) {
        this.document=document;
        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
                                   IntrospectedTable introspectedTable) {

        try {
            //将旧的xml mapper读取到Document中(注意这个Document和上面那个Document不是同一类型,上面那个是mybatis中的)
//            org.mybatis.generator.api.dom.xml.Document
            File directory = shellCallback.getDirectory(sqlMap.getTargetProject(), sqlMap.getTargetPackage());
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(false);
            DocumentBuilder db = dbf.newDocumentBuilder();
            File xmlFile=new File(directory, sqlMap.getFileName());
            if(directory.exists()==false||xmlFile.exists()==false)
                return true;
            Document doc = db.parse(new FileInputStream(xmlFile));
            org.w3c.dom.Element rootElement = doc.getDocumentElement();
            NodeList list = rootElement.getChildNodes();

            List<Element> elements = document.getRootElement().getElements();

            //从node表示的text中读取name和id属性的值,例如<sql id="insert">...</sql>
//            可读取到sql和insert
            Pattern p=Pattern.compile("<(\\w+)\\s+id=\"(\\w+)\"");

            boolean findSameNode=false;
//            遍历新的node,因为做删除操作,这里要用iterator,,
            for (Iterator<Element> elementIt = elements.iterator(); elementIt.hasNext();)
            {
                findSameNode=false;
                String newNodeName="";
                String NewIdValue="";
                Element element=elementIt.next();
                Matcher m=p.matcher(element.getFormattedContent(0));
                if(m.find())
                {
                    //获取新的node的name和id属性的值
                    newNodeName=m.group(1);
                    NewIdValue=m.group(2);
                }
                //遍历旧的node,如果name和id属性的值相同,那么定义为重复,不进行覆盖,从elements中删除
                for(int i=0;i<list.getLength();i++) {
                    Node node = list.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        if(newNodeName.equals(node.getNodeName()))
                        {
                            NamedNodeMap attr = node.getAttributes();
                            for (int j = 0; j < attr.getLength(); j++) {
                                Node attrNode = attr.item(j);
                                if (attrNode.getNodeName().equals("id") &&attrNode.getNodeValue().equals(NewIdValue)) {
                                    //name和ndoe属性值相等,删除并break出去,elementIt->document->新的mapper.xml
                                    elementIt.remove();
                                    findSameNode=true;
                                    break;
                                }
                            }
                            if(findSameNode==true)
                                break;
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return true;
    }

}

主要对比新生成的node和原先存在的node,

只比较mapper下的第一层node,正常是15个.

如果nodeName和id属性的值相同,定义为重复,不覆盖.

如果修改mapper文件修改乱了,把修改乱的哪个node备份,删除掉,重新生成就好了.

举例来说,我修改BaseResultMap改为BaseResultMap1,这样就等于删除了BaseResultMap并且新加了一个BaseResultMap1

然后修改了第三处,加了一个and(测试用的)

重新生成,会重新添加名为BaseResultMap的sql,但是BaseResultMap1和修改的都不会动

(只有缺少的会重新生成)

四.排除的方案

https://my.oschina.net/u/140938/blog/220006

https://my.oschina.net/u/137785/blog/736372

https://stackoverflow.com/questions/43245041/how-could-let-mybatis-generator-overwriting-the-already-generated-mapper-xml

实测:

第二个链接的使用反射修改isMeragale,的确可以解决追加问题,让新生成的覆盖掉,但也将自己新加和修改的给覆盖掉了.

第三个链接直接将旧文件给删除,解决追加问题.

五.使用方法

1.新建一个模块

不能用当前的模块,

如果用当前模块,

当前模块需要maven mybatis generate,而maven mybatis generate需要依赖这个插件类的包才能找到这个类.

所以mybatis需要依赖当前模块的包,但是当前模块的包打包的时候会报错,死循环了.

A在pom中依赖B,配置POM B依赖A,但是maven install A的时候提示B找不到A.

详细说太麻烦了,自己多试试就清楚了.

<?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.haitian</groupId>
    <artifactId>mybatis_plugin</artifactId>
    <version>0.0.1</version>
    <packaging>jar</packaging>

    <name>mybatis_plugin</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>com.haitian</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <mybatis-generator.version>1.3.6</mybatis-generator.version>
        <mysql.version>5.1.13</mysql.version>
        <mybatis.version>3.2.4</mybatis.version>
    </properties>

    <dependencies>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>${mybatis-generator.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
    </dependencies>


</project>

注意不要加plugin

2.添加插件类并install到本地版本库
3.在这里加插件配置
 
   <context id="MBG" targetRuntime="MyBatis3" defaultModelType="conditional">
        <!-- 这个插件给由MBG生成的Java模型对象增加了equals和hashCode方法 -->
        <!--<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin" />-->
        <plugin type="com.haitian.plugins.NoDoubleNodes" />
        <!--<plugin type="com.haitian.plugins.ForceIsMergeablePlugin" />-->
        <commentGenerator>
4.更新mybatis_generator模块的pom

更新dependency为刚才maven install的jar包

   <plugins>
                <plugin>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>${mybatis-generator.version}</version>
                    <configuration>
                        <!-- 指定文件位置好像不起作用,始终默认读取src/main/resources/generatorConfig.xml文件 -->
                        <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                        <verbose>true</verbose>
                        <!--允许覆盖生成的文件-->
                        <overwrite>true</overwrite>
                    </configuration>
                    <!-- 数据库驱动  -->
                    <dependencies>
                        <dependency>
                            <groupId>mysql</groupId>
                            <artifactId>mysql-connector-java</artifactId>
                            <version>${mysql.version}</version>
                        </dependency>

                        <dependency>
                            <groupId>com.haitian</groupId>
                            <artifactId>mybatis_plugin</artifactId>
                            <version>0.0.1</version>
                        </dependency>
                    </dependencies>

                    <!-- 自动生成 -->
                    <executions>
                        <execution>
                            <id>Generate MyBatis Artifacts</id>
                            <goals>
                                <goal>generate</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

结构如下图所示

mybatis_plugin封装插件类并打包,

mybatis-generator-maven-plugin依赖这个包

mybatis_generator调用mybatis-generator-maven-plugin进行generate操作.

 

开发调试的时候最好把maven generate操作之前放上mybatis_plugin的maven打包操作

这样可以即使更新jar资源.

好像不能直接使用模块,只能找jar

六.全部源码和Demo

https://github.com/zwxbest/mybatis-generator-plugin

转载于:https://www.cnblogs.com/ptqueen/p/8390546.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值