一.问题

用的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

mybatis_generator合并xml mapper文件的更多相关文章

  1. mybatis_generator合并xml和Java

    之前写了合并xml的插件,今天改了改mybatis-generator源码,合并java和xml都改进去了. 先上图吧. 左边是一开始生成的,中间去掉author加了password字段和方法,右边重 ...

  2. mybatis xml mapper 文件中 if-else 写法

    mybaits 中没有else要用chose when otherwise 代替 范例一 <!--批量插入用户--> <insert id="insertBusinessU ...

  3. Mybatis学习--Mapper.xml映射文件

    简介 Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. 映射文件中有很多属性,常用的就是parameterType(输入类型 ...

  4. SSM_CRUD新手练习(4)修改生成的mapper.xml映射文件

    我们为什么要修改呢,这是因为我们查询的时候,我们有时候需要连表查询,例如我们需要查询出员工表的信息(emp_id,emp_name...)与此同时,我们还想查询出该员工所在的部门(dept_name) ...

  5. Mapper.xml映射文件

    查询订单关联查询用户: 使用resultType,ordersCustom可以通过继承orders获得其属性,再添加我们需要的用户字段. 使用resultMap,orders表中通过封装user对象来 ...

  6. 5.7 Liquibase:与具体数据库独立的追踪、管理和应用数据库Scheme变化的工具。-mybatis-generator将数据库表反向生成对应的实体类及基于mybatis的mapper接口和xml映射文件(类似代码生成器)

    一. liquibase 使用说明 功能概述:通过xml文件规范化维护数据库表结构及初始化数据. 1.配置不同环境下的数据库信息 (1)创建不同环境的数据库. (2)在resource/liquiba ...

  7. Mybatis中的Mapper.xml映射文件sql查询接收多个参数

    ​ 我们都知道,在Mybatis中的Mapper.xml映射文件可以定制动态SQL,在dao层定义的接口中定义的参数传到xml文件中之后,在查询之前mybatis会对其进行动态解析,通常使用#{}接收 ...

  8. MyBatis 逆向工程——根据数据表自动生成model、xml映射文件、mapper接口

    MyBatis Generator(MBG)的使用 MBG可以根据数据表生成对应的model.xml映射文件.mapper接口,只是简单的生成,还需要根据需求修改. 1.下载jar包 https:// ...

  9. 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

随机推荐

  1. IE、360浏览器select属性onchange遇到的坑

    在网页头部定义js代码 <script type="text/javascript"> function gradeChange(e){ var selectId = ...

  2. Open_stack 有虚拟机端口不通的问题

    原因:流量表 解决办法:not修改流量表(容易出错,出错后果更严重):is迁移虚拟机这样会对应生成新的流量表,然后问题就解决了.

  3. js篇-解析url链接里面的参数名和参数值

    项目背景是,链接为:https://paladin.pingan.com.cn/jf/?appId=PA00200000000_01_APP&id=123456#/fundRank 要求拿到: ...

  4. [js]面向对象2

    delete删除属性 删除对象的属性 删除未用var定义的变量. delete返回布尔 删除不存在的属性,返回true 无法删除原形中的属性 如 delete obj.toString() resu= ...

  5. Go 初体验 - channel.1 - 基本用法

    channel 分为两种: 1. 无缓冲 channel 2. 缓冲 channel 无缓冲 channel 的使用必须遵循一个原则:推送和读取必须同时存在,否则就发生死锁 先上代码: 这里定义了一个 ...

  6. 框架——flask知识点回顾

    1. flask--轻量级Web开发框架 2. Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL 3. Web程序框架的意义: 用于搭建Web应用程序 免去不同Web应用 ...

  7. TheFatRat一般使用

    利用它生成后门 第一种通常情况下速度很快,较稳定,但免杀效果极差 推荐使用第二种 免杀效果好,如下图 第一种是最新的模块,较免杀效果极好.还可伪造图标 第二种是旧的

  8. hdu4777 树状数组

    题意:给了n个数,然后又m次查询,询问[L,R] 内有多少个数与其他的数不互质. 解: 我们首先可以通过处理得出每个数的有效区间,LR 就是 左边L位置上的数 和他不互质, 右边R位置上的数和不互质, ...

  9. hdu5517 二维树状数组

    题意是给了 n个二元组 m个三元组, 二元组可以和三元组 合并生成3元组,合并条件是<a,b> 与<c,d,e>合并成 <a,c,d> 前提是 b==e, 如果存在 ...

  10. Linux安装 centos 7 最小化 安装

    我用的是vmware 15 ,我将用图片的形式带领大家安装,没有说到的地方为默认选项    最好把文件放到一个单独的文件夹中    简单密码点击两次DONE 即可,虚拟机密码不必那么复杂,工作环境请设 ...