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依赖

 		<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency> <!--逆向工程生成-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
</dependency> <dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>

分页配置类

MySQLLimitPlugin.java

package com.meng.device.util;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.XmlConstants;
import org.mybatis.generator.config.PropertyRegistry; import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer; /**
* Created by meng
*/
public class MySQLLimitPlugin extends PluginAdapter { private static String XMLFILE_POSTFIX = "Ext"; private static String JAVAFILE_POTFIX = "Ext"; private static String ANNOTATION_RESOURCE = "javax.annotation.Resource"; @Override
public boolean validate(List<String> list) {
return true;
} /**
* 为每个Example类添加limit和offset属性已经set、get方法
*/
@Override
public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper(); Field limit = new Field();
limit.setName("limit");
limit.setVisibility(JavaVisibility.PRIVATE);
limit.setType(integerWrapper);
topLevelClass.addField(limit); Method setLimit = new Method();
setLimit.setVisibility(JavaVisibility.PUBLIC);
setLimit.setName("setLimit");
setLimit.addParameter(new Parameter(integerWrapper, "limit"));
setLimit.addBodyLine("this.limit = limit;");
topLevelClass.addMethod(setLimit); Method getLimit = new Method();
getLimit.setVisibility(JavaVisibility.PUBLIC);
getLimit.setReturnType(integerWrapper);
getLimit.setName("getLimit");
getLimit.addBodyLine("return limit;");
topLevelClass.addMethod(getLimit); Field offset = new Field();
offset.setName("offset");
offset.setVisibility(JavaVisibility.PRIVATE);
offset.setType(integerWrapper);
topLevelClass.addField(offset); Method setOffset = new Method();
setOffset.setVisibility(JavaVisibility.PUBLIC);
setOffset.setName("setOffset");
setOffset.addParameter(new Parameter(integerWrapper, "offset"));
setOffset.addBodyLine("this.offset = offset;");
topLevelClass.addMethod(setOffset); Method getOffset = new Method();
getOffset.setVisibility(JavaVisibility.PUBLIC);
getOffset.setReturnType(integerWrapper);
getOffset.setName("getOffset");
getOffset.addBodyLine("return offset;");
topLevelClass.addMethod(getOffset); return true;
} // 添删改Document的sql语句及属性
@Override
public boolean sqlMapDocumentGenerated(Document document,
IntrospectedTable introspectedTable) { XmlElement parentElement = document.getRootElement(); // updateDocumentNameSpace(introspectedTable, parentElement); // moveDocumentInsertSql(parentElement);
//
// updateDocumentInsertSelective(parentElement);
//
// moveDocumentUpdateByPrimaryKeySql(parentElement);
//
// generateMysqlPageSql(parentElement, introspectedTable);
//
// generateDataAccessSql(parentElement); return super.sqlMapDocumentGenerated(document, introspectedTable);
} private void updateDocumentNameSpace(IntrospectedTable introspectedTable,
XmlElement parentElement) {
Attribute namespaceAttribute = null;
for (Attribute attribute : parentElement.getAttributes()) {
if (attribute.getName().equals("namespace")) {
namespaceAttribute = attribute;
}
}
parentElement.getAttributes().remove(namespaceAttribute);
parentElement.getAttributes().add(
new Attribute("namespace", introspectedTable
.getMyBatis3JavaMapperType() + JAVAFILE_POTFIX));
} /**
* 为Mapper.xml的selectByExample添加limit
*/
@Override
public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
IntrospectedTable introspectedTable) { XmlElement ifLimitNotNullElement = new XmlElement("if");
ifLimitNotNullElement.addAttribute(new Attribute("test", "limit != null")); XmlElement ifOffsetNotNullElement = new XmlElement("if");
ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null"));
ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${limit}"));
ifLimitNotNullElement.addElement(ifOffsetNotNullElement); XmlElement ifOffsetNullElement = new XmlElement("if");
ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null"));
ifOffsetNullElement.addElement(new TextElement("limit ${limit}"));
ifLimitNotNullElement.addElement(ifOffsetNullElement); element.addElement(ifLimitNotNullElement); return true;
} // 生成XXExt.xml
@Override
public List<GeneratedXmlFile> contextGenerateAdditionalXmlFiles(
IntrospectedTable introspectedTable) { String[] splitFile = introspectedTable.getMyBatis3XmlMapperFileName()
.split("\\.");
String fileNameExt = null;
if (splitFile[0] != null) {
fileNameExt = splitFile[0] + XMLFILE_POSTFIX + ".xml";
} if (isExistExtFile(context.getSqlMapGeneratorConfiguration()
.getTargetProject(),
introspectedTable.getMyBatis3XmlMapperPackage(), fileNameExt)) {
return super.contextGenerateAdditionalXmlFiles(introspectedTable);
} Document document = new Document(
XmlConstants.MYBATIS3_MAPPER_PUBLIC_ID,
XmlConstants.MYBATIS3_MAPPER_SYSTEM_ID); XmlElement root = new XmlElement("mapper");
document.setRootElement(root);
String namespace = introspectedTable.getMyBatis3SqlMapNamespace()
+ XMLFILE_POSTFIX;
root.addAttribute(new Attribute("namespace", namespace)); GeneratedXmlFile gxf = new GeneratedXmlFile(document, fileNameExt,
introspectedTable.getMyBatis3XmlMapperPackage(), context
.getSqlMapGeneratorConfiguration().getTargetProject(),
false, context.getXmlFormatter()); List<GeneratedXmlFile> answer = new ArrayList<GeneratedXmlFile>(1);
answer.add(gxf); return answer;
} // 生成XXExt.java
@Override
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(
IntrospectedTable introspectedTable) { FullyQualifiedJavaType type = new FullyQualifiedJavaType(
introspectedTable.getMyBatis3JavaMapperType() + JAVAFILE_POTFIX);
Interface interfaze = new Interface(type);
interfaze.setVisibility(JavaVisibility.PUBLIC);
context.getCommentGenerator().addJavaFileComment(interfaze); FullyQualifiedJavaType baseInterfaze = new FullyQualifiedJavaType(
introspectedTable.getMyBatis3JavaMapperType());
interfaze.addSuperInterface(baseInterfaze); FullyQualifiedJavaType annotation = new FullyQualifiedJavaType(
ANNOTATION_RESOURCE);
interfaze.addAnnotation("@Resource");
interfaze.addImportedType(annotation); CompilationUnit compilationUnits = interfaze;
GeneratedJavaFile generatedJavaFile = new GeneratedJavaFile(
compilationUnits,
context.getJavaModelGeneratorConfiguration().getTargetProject(),
context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
context.getJavaFormatter()); if (isExistExtFile(generatedJavaFile.getTargetProject(),
generatedJavaFile.getTargetPackage(),
generatedJavaFile.getFileName())) {
return super.contextGenerateAdditionalJavaFiles(introspectedTable);
}
List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<GeneratedJavaFile>(
1);
generatedJavaFile.getFileName();
generatedJavaFiles.add(generatedJavaFile);
return generatedJavaFiles;
} private boolean isExistExtFile(String targetProject, String targetPackage,
String fileName) { File project = new File(targetProject);
if (!project.isDirectory()) {
return true;
} StringBuilder sb = new StringBuilder();
StringTokenizer st = new StringTokenizer(targetPackage, ".");
while (st.hasMoreTokens()) {
sb.append(st.nextToken());
sb.append(File.separatorChar);
} File directory = new File(project, sb.toString());
if (!directory.isDirectory()) {
boolean rc = directory.mkdirs();
if (!rc) {
return true;
}
} File testFile = new File(directory, fileName);
if (testFile.exists()) {
return true;
} else {
return false;
}
}
}

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

generatorConfig_local.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration>
<!--<classPathEntry location="C:/Project/DB/mysql-connector-java-5.1.40-bin.jar"/>-->
<context id="base_resource" targetRuntime="MyBatis3"> <property name="useActualColumnNames" value="false"/> <plugin type="com.meng.device.util.MySQLLimitPlugin"/> <commentGenerator>
<property name="suppressDate" value="true"/>
</commentGenerator> <jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&amp;characterEncoding=UTF-8"
userId="root"
password="root">
</jdbcConnection> <!-- targetProject:生成PO类的位置 根据自己项目位置更改 -->
<javaModelGenerator targetPackage="com.meng.device.dao"
targetProject="E:\project\IdeaProjects\device\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="true"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 根据自己项目位置更改-->
<sqlMapGenerator targetPackage="com.meng.device.mapper"
targetProject="E:\project\IdeaProjects\device\src\main\resources">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 根据自己项目位置更改-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.meng.device.mapper"
targetProject="E:\project\IdeaProjects\device\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="true"/>
</javaClientGenerator> <!-- 指定数据库表 -->
<!--映射表名 多个表可以写多个-->
<!--<table tableName="表名" domainObjectName="实体名">
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>--> <!-- 有些表的字段需要指定java类型 <table schema=""tableName=""> <columnOverridecolumn="" javaType="" /> </table> --> </context>
</generatorConfiguration>

启动类

Generator.java

package com.meng.device.generator;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback; import java.util.ArrayList;
import java.util.List; /**
* @description: mybatis逆向工程 自动生成mybatis-Mapper工具
* @author: meng
* @create: 2019-09-11 08:58
**/
public class Generator { /**
* 目前在系统中本地环境使用local来配置mapper生成规则
*/
//指定逆向工程配置文件
private static final String config_url = "generatorConfig_local.xml"; public void generator() throws Exception {
List<String> warnings = new ArrayList<String>();
ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(Generator.class.getClassLoader().getResourceAsStream(config_url)); DefaultShellCallback callback = new DefaultShellCallback(true);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
} /**
* 主函数
*/
public static void main(String[] args) throws Exception {
try {
Generator generatorSqlmap = new Generator();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("generator 执行成功!");
} }

配置完成后执行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. GAN 原理及公式推导

    Generative Adversarial Network,就是大家耳熟能详的 GAN,由 Ian Goodfellow 首先提出,在这两年更是深度学习中最热门的东西,仿佛什么东西都能由 GAN 做 ...

  2. FLUENT不同求解器离散格式选择【转载】

    转载自:http://blog.163.com/wu_yangfeng/blog/static/16189737920104158950438/ 离散格式对求解器性能的影响 控制方程的扩散项一般采用中 ...

  3. Open vSwitch系列实验(三):Open vSwitch的VxLAN隧道网络实验

    1 实验目的 该实验通过Open vSwitch构建Overlay的VxLAN网络,更直观的展现VxLAN的优势.在实验过程中,可以了解如何建立VxLAN隧道并进行配置,并实现相同网段和不同网段之间的 ...

  4. 深度学习面试题07:sigmod交叉熵、softmax交叉熵

    目录 sigmod交叉熵 Softmax转换 Softmax交叉熵 参考资料 sigmod交叉熵 Sigmod交叉熵实际就是我们所说的对数损失,它是针对二分类任务的损失函数,在神经网络中,一般输出层只 ...

  5. arcgis python 获得arcgis的版本和安装路径

    import arcpy # Use the dictionary iteritems to iterate through # the key/value pairs from GetInstall ...

  6. Fiddler查看request是由哪一个process发起的

    有一个Process列 查看到进程编号是24836 然后用chrome自带的TaskManager查看对应的是哪一个进程 https://www.lifewire.com/google-chrome- ...

  7. seekBar拖动滑块

    中秋节学习,, 通过拖动滑块,改变图片的透明度 <?xml version="1.0" encoding="utf-8"?> <LinearL ...

  8. Python3基础 bool True为1 False为0

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  9. netty5服务端检测心跳超时断连

    客户端每5秒发送一次心跳给服务端,服务端记录最后一次心跳时间,通过定时任务每10秒检测一下,如果当前时间与最后一次收到的心跳时间之差超过某个阈值,断开与客户端的连接.基于之前的例子(netty5心跳与 ...

  10. SQL查询优化 LEFT JOIN和INNER JOIN

    作者:VerySky 推荐:陈敬(Cathy) SQL查询优化 LEFT JOIN和INNER JOIN 1,连接了八个数据库表,而且全部使用LEFT JOIN,如下所示: Resource_Reso ...