MyBatis逆向工程生成

mybatis需要程序员自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java、mapper.xml、pojo…),可以让程序员将更多的精力放在繁杂的业务逻辑上。

企业实际开发中,常用的逆向工程方式:由数据库的表生成java代码。

​ 之所以强调单表两个字,是因为Mybatis逆向工程生成的Mapper所进行的操作都是针对单表的,也许你可能会觉得那这就有点鸡肋了,但是在大型项目中,很少有复杂的多表关联查询,所以作用还是很大的。

介绍

MyBatis生成器(MBG)是MyBatis MyBatisiBATIS的代码生成器。它将为MyBatis的所有版本以及版本2.2.0之后的iBATIS生成代码。它将内省一个数据库表(或多个表),并将生成可用于访问表的工件。这减轻了设置对象和配置文件以与数据库表进行交互的麻烦。MBG试图对简单CRUD(创建,检索,更新,删除)的大部分数据库操作产生重大影响。您仍将需要手工编写SQL和对象代码以进行联接查询或存储过程。

官方仓库 官方文档

开始上代码

目录总体结构:

主要文件

pom依赖

  1. <!--mybatis依赖-->
  2. <dependency>
  3. <groupId>org.mybatis.spring.boot</groupId>
  4. <artifactId>mybatis-spring-boot-starter</artifactId>
  5. <version>1.3.2</version>
  6. </dependency>
  7. <!--逆向工程生成-->
  8. <dependency>
  9. <groupId>org.mybatis.generator</groupId>
  10. <artifactId>mybatis-generator-maven-plugin</artifactId>
  11. <version>1.3.5</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.mybatis.generator</groupId>
  15. <artifactId>mybatis-generator-core</artifactId>
  16. <version>1.3.5</version>
  17. </dependency>

分页配置类

MySQLLimitPlugin.java

  1. package com.meng.device.util;
  2. import org.mybatis.generator.api.GeneratedJavaFile;
  3. import org.mybatis.generator.api.GeneratedXmlFile;
  4. import org.mybatis.generator.api.IntrospectedTable;
  5. import org.mybatis.generator.api.PluginAdapter;
  6. import org.mybatis.generator.api.dom.java.*;
  7. import org.mybatis.generator.api.dom.xml.Attribute;
  8. import org.mybatis.generator.api.dom.xml.Document;
  9. import org.mybatis.generator.api.dom.xml.TextElement;
  10. import org.mybatis.generator.api.dom.xml.XmlElement;
  11. import org.mybatis.generator.codegen.XmlConstants;
  12. import org.mybatis.generator.config.PropertyRegistry;
  13. import java.io.File;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import java.util.StringTokenizer;
  17. /**
  18. * Created by meng
  19. */
  20. public class MySQLLimitPlugin extends PluginAdapter {
  21. private static String XMLFILE_POSTFIX = "Ext";
  22. private static String JAVAFILE_POTFIX = "Ext";
  23. private static String ANNOTATION_RESOURCE = "javax.annotation.Resource";
  24. @Override
  25. public boolean validate(List<String> list) {
  26. return true;
  27. }
  28. /**
  29. * 为每个Example类添加limit和offset属性已经set、get方法
  30. */
  31. @Override
  32. public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  33. PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper();
  34. Field limit = new Field();
  35. limit.setName("limit");
  36. limit.setVisibility(JavaVisibility.PRIVATE);
  37. limit.setType(integerWrapper);
  38. topLevelClass.addField(limit);
  39. Method setLimit = new Method();
  40. setLimit.setVisibility(JavaVisibility.PUBLIC);
  41. setLimit.setName("setLimit");
  42. setLimit.addParameter(new Parameter(integerWrapper, "limit"));
  43. setLimit.addBodyLine("this.limit = limit;");
  44. topLevelClass.addMethod(setLimit);
  45. Method getLimit = new Method();
  46. getLimit.setVisibility(JavaVisibility.PUBLIC);
  47. getLimit.setReturnType(integerWrapper);
  48. getLimit.setName("getLimit");
  49. getLimit.addBodyLine("return limit;");
  50. topLevelClass.addMethod(getLimit);
  51. Field offset = new Field();
  52. offset.setName("offset");
  53. offset.setVisibility(JavaVisibility.PRIVATE);
  54. offset.setType(integerWrapper);
  55. topLevelClass.addField(offset);
  56. Method setOffset = new Method();
  57. setOffset.setVisibility(JavaVisibility.PUBLIC);
  58. setOffset.setName("setOffset");
  59. setOffset.addParameter(new Parameter(integerWrapper, "offset"));
  60. setOffset.addBodyLine("this.offset = offset;");
  61. topLevelClass.addMethod(setOffset);
  62. Method getOffset = new Method();
  63. getOffset.setVisibility(JavaVisibility.PUBLIC);
  64. getOffset.setReturnType(integerWrapper);
  65. getOffset.setName("getOffset");
  66. getOffset.addBodyLine("return offset;");
  67. topLevelClass.addMethod(getOffset);
  68. return true;
  69. }
  70. // 添删改Document的sql语句及属性
  71. @Override
  72. public boolean sqlMapDocumentGenerated(Document document,
  73. IntrospectedTable introspectedTable) {
  74. XmlElement parentElement = document.getRootElement();
  75. // updateDocumentNameSpace(introspectedTable, parentElement);
  76. // moveDocumentInsertSql(parentElement);
  77. //
  78. // updateDocumentInsertSelective(parentElement);
  79. //
  80. // moveDocumentUpdateByPrimaryKeySql(parentElement);
  81. //
  82. // generateMysqlPageSql(parentElement, introspectedTable);
  83. //
  84. // generateDataAccessSql(parentElement);
  85. return super.sqlMapDocumentGenerated(document, introspectedTable);
  86. }
  87. private void updateDocumentNameSpace(IntrospectedTable introspectedTable,
  88. XmlElement parentElement) {
  89. Attribute namespaceAttribute = null;
  90. for (Attribute attribute : parentElement.getAttributes()) {
  91. if (attribute.getName().equals("namespace")) {
  92. namespaceAttribute = attribute;
  93. }
  94. }
  95. parentElement.getAttributes().remove(namespaceAttribute);
  96. parentElement.getAttributes().add(
  97. new Attribute("namespace", introspectedTable
  98. .getMyBatis3JavaMapperType() + JAVAFILE_POTFIX));
  99. }
  100. /**
  101. * 为Mapper.xml的selectByExample添加limit
  102. */
  103. @Override
  104. public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
  105. IntrospectedTable introspectedTable) {
  106. XmlElement ifLimitNotNullElement = new XmlElement("if");
  107. ifLimitNotNullElement.addAttribute(new Attribute("test", "limit != null"));
  108. XmlElement ifOffsetNotNullElement = new XmlElement("if");
  109. ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null"));
  110. ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${limit}"));
  111. ifLimitNotNullElement.addElement(ifOffsetNotNullElement);
  112. XmlElement ifOffsetNullElement = new XmlElement("if");
  113. ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null"));
  114. ifOffsetNullElement.addElement(new TextElement("limit ${limit}"));
  115. ifLimitNotNullElement.addElement(ifOffsetNullElement);
  116. element.addElement(ifLimitNotNullElement);
  117. return true;
  118. }
  119. // 生成XXExt.xml
  120. @Override
  121. public List<GeneratedXmlFile> contextGenerateAdditionalXmlFiles(
  122. IntrospectedTable introspectedTable) {
  123. String[] splitFile = introspectedTable.getMyBatis3XmlMapperFileName()
  124. .split("\\.");
  125. String fileNameExt = null;
  126. if (splitFile[0] != null) {
  127. fileNameExt = splitFile[0] + XMLFILE_POSTFIX + ".xml";
  128. }
  129. if (isExistExtFile(context.getSqlMapGeneratorConfiguration()
  130. .getTargetProject(),
  131. introspectedTable.getMyBatis3XmlMapperPackage(), fileNameExt)) {
  132. return super.contextGenerateAdditionalXmlFiles(introspectedTable);
  133. }
  134. Document document = new Document(
  135. XmlConstants.MYBATIS3_MAPPER_PUBLIC_ID,
  136. XmlConstants.MYBATIS3_MAPPER_SYSTEM_ID);
  137. XmlElement root = new XmlElement("mapper");
  138. document.setRootElement(root);
  139. String namespace = introspectedTable.getMyBatis3SqlMapNamespace()
  140. + XMLFILE_POSTFIX;
  141. root.addAttribute(new Attribute("namespace", namespace));
  142. GeneratedXmlFile gxf = new GeneratedXmlFile(document, fileNameExt,
  143. introspectedTable.getMyBatis3XmlMapperPackage(), context
  144. .getSqlMapGeneratorConfiguration().getTargetProject(),
  145. false, context.getXmlFormatter());
  146. List<GeneratedXmlFile> answer = new ArrayList<GeneratedXmlFile>(1);
  147. answer.add(gxf);
  148. return answer;
  149. }
  150. // 生成XXExt.java
  151. @Override
  152. public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(
  153. IntrospectedTable introspectedTable) {
  154. FullyQualifiedJavaType type = new FullyQualifiedJavaType(
  155. introspectedTable.getMyBatis3JavaMapperType() + JAVAFILE_POTFIX);
  156. Interface interfaze = new Interface(type);
  157. interfaze.setVisibility(JavaVisibility.PUBLIC);
  158. context.getCommentGenerator().addJavaFileComment(interfaze);
  159. FullyQualifiedJavaType baseInterfaze = new FullyQualifiedJavaType(
  160. introspectedTable.getMyBatis3JavaMapperType());
  161. interfaze.addSuperInterface(baseInterfaze);
  162. FullyQualifiedJavaType annotation = new FullyQualifiedJavaType(
  163. ANNOTATION_RESOURCE);
  164. interfaze.addAnnotation("@Resource");
  165. interfaze.addImportedType(annotation);
  166. CompilationUnit compilationUnits = interfaze;
  167. GeneratedJavaFile generatedJavaFile = new GeneratedJavaFile(
  168. compilationUnits,
  169. context.getJavaModelGeneratorConfiguration().getTargetProject(),
  170. context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
  171. context.getJavaFormatter());
  172. if (isExistExtFile(generatedJavaFile.getTargetProject(),
  173. generatedJavaFile.getTargetPackage(),
  174. generatedJavaFile.getFileName())) {
  175. return super.contextGenerateAdditionalJavaFiles(introspectedTable);
  176. }
  177. List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<GeneratedJavaFile>(
  178. 1);
  179. generatedJavaFile.getFileName();
  180. generatedJavaFiles.add(generatedJavaFile);
  181. return generatedJavaFiles;
  182. }
  183. private boolean isExistExtFile(String targetProject, String targetPackage,
  184. String fileName) {
  185. File project = new File(targetProject);
  186. if (!project.isDirectory()) {
  187. return true;
  188. }
  189. StringBuilder sb = new StringBuilder();
  190. StringTokenizer st = new StringTokenizer(targetPackage, ".");
  191. while (st.hasMoreTokens()) {
  192. sb.append(st.nextToken());
  193. sb.append(File.separatorChar);
  194. }
  195. File directory = new File(project, sb.toString());
  196. if (!directory.isDirectory()) {
  197. boolean rc = directory.mkdirs();
  198. if (!rc) {
  199. return true;
  200. }
  201. }
  202. File testFile = new File(directory, fileName);
  203. if (testFile.exists()) {
  204. return true;
  205. } else {
  206. return false;
  207. }
  208. }
  209. }

主要配置 映射哪些表也是在这个里面配置(每次只需要修改这个)

generatorConfig_local.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE generatorConfiguration
  3. PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  4. "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
  5. <generatorConfiguration>
  6. <!--<classPathEntry location="C:/Project/DB/mysql-connector-java-5.1.40-bin.jar"/>-->
  7. <context id="base_resource" targetRuntime="MyBatis3">
  8. <property name="useActualColumnNames" value="false"/>
  9. <plugin type="com.meng.device.util.MySQLLimitPlugin"/>
  10. <commentGenerator>
  11. <property name="suppressDate" value="true"/>
  12. </commentGenerator>
  13. <jdbcConnection driverClass="com.mysql.jdbc.Driver"
  14. connectionURL="jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&amp;characterEncoding=UTF-8"
  15. userId="root"
  16. password="root">
  17. </jdbcConnection>
  18. <!-- targetProject:生成PO类的位置 根据自己项目位置更改 -->
  19. <javaModelGenerator targetPackage="com.meng.device.dao"
  20. targetProject="E:\project\IdeaProjects\device\src\main\java">
  21. <!-- enableSubPackages:是否让schema作为包的后缀 -->
  22. <property name="enableSubPackages" value="true"/>
  23. <!-- 从数据库返回的值被清理前后的空格 -->
  24. <property name="trimStrings" value="true"/>
  25. </javaModelGenerator>
  26. <!-- targetProject:mapper映射文件生成的位置 根据自己项目位置更改-->
  27. <sqlMapGenerator targetPackage="com.meng.device.mapper"
  28. targetProject="E:\project\IdeaProjects\device\src\main\resources">
  29. <!-- enableSubPackages:是否让schema作为包的后缀 -->
  30. <property name="enableSubPackages" value="true"/>
  31. </sqlMapGenerator>
  32. <!-- targetPackage:mapper接口生成的位置 根据自己项目位置更改-->
  33. <javaClientGenerator type="XMLMAPPER" targetPackage="com.meng.device.mapper"
  34. targetProject="E:\project\IdeaProjects\device\src\main\java">
  35. <!-- enableSubPackages:是否让schema作为包的后缀 -->
  36. <property name="enableSubPackages" value="true"/>
  37. </javaClientGenerator>
  38. <!-- 指定数据库表 -->
  39. <!--映射表名 多个表可以写多个-->
  40. <!--<table tableName="表名" domainObjectName="实体名">
  41. <property name="useActualColumnNames" value="false"/>
  42. <generatedKey column="id" sqlStatement="MySql" identity="true"/>
  43. </table>-->
  44. <!-- 有些表的字段需要指定java类型
  45. <table schema=""tableName="">
  46. <columnOverridecolumn="" javaType="" />
  47. </table> -->
  48. </context>
  49. </generatorConfiguration>

启动类

Generator.java

  1. package com.meng.device.generator;
  2. import org.mybatis.generator.api.MyBatisGenerator;
  3. import org.mybatis.generator.config.Configuration;
  4. import org.mybatis.generator.config.xml.ConfigurationParser;
  5. import org.mybatis.generator.internal.DefaultShellCallback;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. /**
  9. * @description: mybatis逆向工程 自动生成mybatis-Mapper工具
  10. * @author: meng
  11. * @create: 2019-09-11 08:58
  12. **/
  13. public class Generator {
  14. /**
  15. * 目前在系统中本地环境使用local来配置mapper生成规则
  16. */
  17. //指定逆向工程配置文件
  18. private static final String config_url = "generatorConfig_local.xml";
  19. public void generator() throws Exception {
  20. List<String> warnings = new ArrayList<String>();
  21. ConfigurationParser cp = new ConfigurationParser(warnings);
  22. Configuration config = cp.parseConfiguration(Generator.class.getClassLoader().getResourceAsStream(config_url));
  23. DefaultShellCallback callback = new DefaultShellCallback(true);
  24. MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
  25. myBatisGenerator.generate(null);
  26. }
  27. /**
  28. * 主函数
  29. */
  30. public static void main(String[] args) throws Exception {
  31. try {
  32. Generator generatorSqlmap = new Generator();
  33. generatorSqlmap.generator();
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. System.out.println("generator 执行成功!");
  38. }
  39. }

配置完成后执行Generator类中主函数

MyBatis逆向工程生成配置 generator (生成pojo、mapper.xml、mapper.java)的更多相关文章

  1. spring mybatis 整合问题Error parsing Mapper XML. Cause: java.lang.NullPointerException

    14:30:40,872 DEBUG SqlSessionFactoryBean:431 - Parsed configuration file: 'class path resource [myba ...

  2. Spring 与 mybatis整合 Error parsing Mapper XML. Cause: java.lang.NullPointerException

    mapper配置文件中的namespace没有填:而且namespase的值应该填为:mapper的权限定名:否则还是会抛出异常 org.springframework.beans.factory.B ...

  3. nested exception is java.lang.RuntimeException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps collection already contains value for

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'daoSupport': ...

  4. MyBatis逆向工程:根据table生成Model、Mapper、Mapper.xml

    逆向工程工具 下载地址:https://download.csdn.net/download/zhutouaizhuwxd/10779140 1.工程导入Eclipse  2.运行MainUI.jav ...

  5. mybatis逆向工程之配置

    逆向工程1.什么是逆向工程mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml. ...

  6. Mybatis逆向工程的配置

    源码github下载地址:https://github.com/wcyong/mybatisGeneratorCustom.git 参考文章:https://www.cnblogs.com/whgk/ ...

  7. Spring Boot整合tk.mybatis及pageHelper分页插件及mybatis逆向工程

    Spring Boot整合druid数据源 1)引入依赖 <dependency> <groupId>com.alibaba</groupId> <artif ...

  8. mybatis逆向工程自动生成实体类、接口以及映射Mapper.xml配置文件

    Mybatis的逆向工程非常简单,只要一个配置文件和一个Main方法就可以实现,下面以maven工程为例: (1)在pom.xml中引入依赖包 <dependency> <group ...

  9. 回顾一下MyBatis逆向工程——自动生成代码

    前言 最近做的项目(SSM+Shiro)的数据库表已经创建完成,一共有15张表,如果我们一个个去写pojo/bean的代码以及各种sql语句的话未免太过麻烦而且很容易出错,这个时候我们就需要MyBat ...

随机推荐

  1. nginx代理mysql

    实验环境: 两台编译安装的mysql                            一台编译安装的nginx 192.168.3.1                               ...

  2. Spring boot 去除URL 里的 JSESSIONID

    方法一 application.yml 里设置 server: port: 80 servlet: session: tracking-modes: cookie cookie: http-only: ...

  3. ADO.NET五大对象增删改查使用

    string ConnStr = "Data Source=.;Initial Catalog=ADO_DEMO;Integrated Security=True"; #regio ...

  4. Android Mboot mmc命令介绍

    mmc command.         目前Mboot支持以下mmc命令: 1) mmc read/write.    读写命令.Addr = 内存地址, blk# = 起始block数, size ...

  5. taocrypt

    taocrypt MySQL Bugs: #25189: mysqld: coding.cpp:243: void TaoCrypt::Base64Decoder::Decode(): Asserti ...

  6. uefi下如何启动linux?

    1. 有两种方式 1.1 直接从uefi shell启动linux内核 1.2 从uefi shell启动grub,然后再从grub启动linux内核 2. 需要哪些东西? 2.1 linux内核 2 ...

  7. IDEA分配内存无效

    idea改启动内存分配, 改 C:/Users/xxx/.IntelliJIdea2018.1/confing/idea64.exe.vmoptions 或 C:/Users/xxx/.Intelli ...

  8. 为什么vue组件的属性,有的需要加冒号“:”,有的不用?

    https://segmentfault.com/q/1010000010929963/a-1020000010930077 <tab :line-width="2" act ...

  9. Python中__new__和__init__的区别与联系

    __new__ 负责对象的创建而 __init__ 负责对象的初始化. __new__:创建对象时调用,会返回当前对象的一个实例 __init__:创建完对象后调用,对当前对象的一些实例初始化,无返回 ...

  10. jenkins结合httprunner配置实现自动化测试

    jenkins结合httprunner配置实现自动化测试 自动化测试思路: jenkins发布代码到预发布环境 –> 触发自动化测试预发布环境 à 返回测试结:如果测试通过则将代码推送到生产环境 ...