【问题标题】:How could let MyBatis Generator overwriting the already generated *Mapper.xml?怎么可能让 MyBatis Generator 覆盖已经生成的 *Mapper.xml?
【发布时间】:2017-08-31 21:15:17
【问题描述】:

像标题一样,当我执行 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 中,我尝试覆盖配置。 所有的配置都行不通。

如何修改配置?

【问题讨论】:

    标签: maven pom.xml mybatis overwrite mybatis-generator


    【解决方案1】:

    如果找到匹配项,MyBatis 生成器将始终合并 XML 文件。目前没有关闭它的选项。

    【讨论】:

      【解决方案2】:

      可以使用Mybatis Generator 1.3.7中的插件&lt;plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" /&gt;覆盖xml。

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

      此插件将禁用生成的映射器 XML 文件的 XML 合并功能。这将导致生成器以与 Java 文件相同的方式尊重 XML 文件的覆盖标志 - 如果覆盖为真,则现有文件将被覆盖,否则将使用唯一名称写入新文件。

      如果您禁用所有 cmets,此插件会很有帮助。

      在Mybatis Generator配置文件中设置&lt;property name="suppressAllComments" value="true" /&gt;会导致这个问题。 Mybatis Generator 使用 cmets flag 来决定是否合并 XML。

      如果禁用所有 cmets,您可能会发现 UnmergeableXmlMappersPlugin 很有用。这将使生成器尊重 XML 文件的覆盖标志。

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

      【讨论】:

        【解决方案3】:

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

        mybatis-generator-config.xml:

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

        删除现有SqlMapsPlugin.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 文件在内存中创建之后但在写入磁盘之前被调用。

        【讨论】:

        • 不应该是sqlMap.getTargetPackage().replaceAll("\\.", Matcher.quoteReplacement(File.separator)) 吗?
        【解决方案4】:

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

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

        【讨论】:

        • 我将 1.3.5 修改为 1.3.4-SNAPSHOT,但对我不起作用。
        【解决方案5】:

        我写了一个插件来合并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映射器文件,只会生成insertSelective,其他的不会被覆盖。

        【讨论】:

          猜你喜欢
          • 2023-03-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-10
          • 1970-01-01
          • 1970-01-01
          • 2012-10-18
          • 1970-01-01
          相关资源
          最近更新 更多