怎么让 MyBatis Generator 覆盖掉已经生成的 *Mapper.xml?

How could let MyBatis Generator overwriting the already generated *Mapper.xml?

如题,执行mybatis-generator时,我想覆盖掉已经生成的*Mapper.xml所有,而不是合并! 但是我尝试了很多配置方式,它没有实现正确。 并且每次 xml 内容生成的次数越多。 像这样:

<resultMap id="BaseResultMap" type="com.test.entity.GoodsEntity"> ...
<resultMap id="BaseResultMap" type="com.test.entity.GoodsEntity"> ...
<resultMap id="BaseResultMap" type="com.test.entity.GoodsEntity"> ...

在属性中,我添加了这一行:

<mybatis.generator.overwrite>true</mybatis.generator.overwrite>

在构建 > 插件中,我添加以下行:

<plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version>
            <configuration>
                <verbose>true</verbose>
                <overwrite>true</overwrite>
                <configurationFile>${mybatis.generator.configurationFile}</configurationFile>
            </configuration>
            <executions>
                <execution>
                    <id>Generate MyBatis Artifacts</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>com.test</groupId>
                    <artifactId>ob-maven-plugin-mybatis-generator</artifactId>
                    <version>1.0</version>
                </dependency>
            </dependencies>
        </plugin>

在mybatis-generator.xml中,我尝试覆盖配置。 所有配置都不起作用。

如何修改配置?

我遇到了同样的问题today.To解决了这个问题,只需要更改mybatis-generator-maven-plugin的版本即可。

<mybatis-generator-maven-plugin.version>1.3.4-SNAPSHOT</mybatis-generator-maven-plugin.version>

MyBatis 生成器如果找到匹配,总是会合并 XML 个文件。目前没有关闭它的选项。

我可以通过创建一个插件并将其添加到 mybatis-generator-config.xml 文件来解决这个问题。 当然请注意,无论是否指定 -overwrite 标志,此解决方案都会导致 Mapper.xml 文件始终被覆盖。

mybatis-generator-config.xml:

<generatorConfiguration>
    ...
    <context id="myContextId">
        <plugin type="com.mydomain.DeleteExistingSqlMapsPlugin"></plugin>
        ...
    </context>
</generatorConfiguration>

DeleteExistingSqlMapsPlugin.java:

...
public class DeleteExistingSqlMapsPlugin extends PluginAdapter {

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

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
            IntrospectedTable introspectedTable)
    {
        String sqlMapPath = sqlMap.getTargetProject() + File.separator
                + sqlMap.getTargetPackage().replaceAll("\.", File.separator)
                + File.separator + sqlMap.getFileName();
        File sqlMapFile = new File(sqlMapPath);

        sqlMapFile.delete();

        return true;
    }

}

这是有效的,因为 sqlMapGenerated() 在 Mapper.xml 文件在内存中创建之后但在写入磁盘之前被调用。

我写了一个插件来合并 xml 映射器文件。

并修改 mybatis-generator-core 以合并 java 和 xml.

这可以使您的 xml 和 java 文件的修改不被覆盖。

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

用法:

<generatorConfiguration>
    ...
    <context id="myContextId">
        <plugin type="com.mydomain.CombineXmlPlugin"></plugin>
        ...
    </context>
</generatorConfiguration>

插件代码:

    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:
 * old nodes is your existing xml file's first level nodes,like <insert><resultMap>
 *  new nodes is mybatis-generator generate for you to combine
 * This compare the first level node's name and "id" attribute of new nodes and old nodes
 * if the two equal,then new node will not generate
 * so this can make you modification in old nodes not override.
 * if you want to regenrate old node,delete it,it will generate new.
 */
public class CombineXmlPlugin extends PluginAdapter {
    //shellCallback use TargetProject and TargetPackage to get targetFile
    ShellCallback shellCallback = new DefaultShellCallback(false);
    //save new nodes
    org.mybatis.generator.api.dom.xml.Document document;

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

    /**
     * assing document variable to get new nodes
     * @param document
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean sqlMapDocumentGenerated(org.mybatis.generator.api.dom.xml.Document document,
                                           IntrospectedTable introspectedTable) {
        this.document = document;
        return true;
    }


    //new nodes is generated,but not write on disk,we just need to filter.
    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
                                   IntrospectedTable introspectedTable) {

        try {
            //get old nodes
            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();
            //get new nodes
            List<Element> elements = document.getRootElement().getElements();

            //get nodeName and the value of id attribute use regex
            Pattern p = Pattern.compile("<(\w+)\s+id=\"(\w+)\"");

            boolean findSameNode = false;
            // traverse new nodes to compare old nodes to filter
            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()) {
                  //get nodeName and the value of id attribute
                    newNodeName = m.group(1);
                    NewIdValue = m.group(2);
                }
                //if the nodeName of newNode and oldNode are equal
                //and the id attribute of newNode and oldNode are equal
                //then filter newNode
                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)) {
                                    //filter new node,just delete it ,and it will not generate
                                    elementIt.remove();
                                    findSameNode = true;
                                    break;
                                }
                            }
                            if (findSameNode == true)
                                break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}

您添加 "batchInsert",删除 insertSelective,并修改其他节点。 然后重新生成xml mapper文件,只会生成insertSelective,其他的不会被override。

Mybatis Generator 1.3.7可以使用插件<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />覆盖xml.

http://www.mybatis.org/generator/reference/plugins.html

This plugin will disable the XML merge function for generated mapper XML files. This will cause the generator to respect the overwrite flag for XML files in the same way it does for Java files - if overwrite is true, then an existing file will be overwritten, else a new file will be written with a unique name.

This plugin can be helpful if you disable all comments.

在Mybatis Generator配置文件中设置<property name="suppressAllComments" value="true" />会导致这个问题。 Mybatis Generator 使用注释标志来决定是否合并 XML.

If you disable all comments, you might find the UnmergeableXmlMappersPlugin useful. It will cause the generator to respect the overwrite flag for XML files.

http://www.mybatis.org/generator/configreference/commentGenerator.html