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. docker安装postgresql

    1.在linux执行以下代码: docker run -p : -v /home/docker/postgresql/data:/var/lib/postgresql/data -e POSTGRES ...

  2. 【BZOJ】BZOJ3040 最短路 线段树优化Dijkstra

    题目描述 N个点,M条边的有向图,求点1到点N的最短路(保证存在). 1<=N<=1000000,1<=M<=10000000 输入格式 第一行两个整数N.M,表示点数和边数. ...

  3. Chrome远程调试之WebSocket

    var ws = new WebSocket('ws://localhost:9222/devtools/page/3c5c05fa-80b7-4cfe-8d1d-ebe79a7a5730');ws. ...

  4. 第10组 Alpha冲刺(2/6)

    链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 了解了如何根据系统获取的实际情况进行后端任务的调整 网易云音乐推荐算法的分析 ...

  5. cropper.js移动端使用

    cropper.js移动端使用 一.总结 一句话总结: 启示:找对关键词,找对相关方面的应用,效果真的非常好 比如 cropper.js移动端使用,这样设置了(dragMode: 'move',//拖 ...

  6. sql server for centos7

    sql server for centos7 笔者在CENTOS7上面安装SQL SERVER,感觉非常方便. 但有一点要注意,字段是字符串类型的,要使用nvarchar(),不能使用varchar( ...

  7. ISO/IEC 9899:2011 条款6.6——常量表达式

    6.6 常量表达式 语法 1.constant-expression conditional-expression 描述 2.一个常量表达式可以在翻译期间被计算,而不是在运行时,并且根据情况可以被用于 ...

  8. spring boot集成Websocket

    websocket实现后台像前端主动推送消息的模式,可以减去前端的请求获取数据的模式.而后台主动推送消息一般都是要求消息回馈比较及时,同时减少前端ajax轮询请求,减少资源开销. spring boo ...

  9. 0.9.0.RELEASE版本的spring cloud alibaba sentinel+gateway网关实例

    sentinel除了让服务提供方.消费方用之外,网关也能用它来限流.我们基于上次整的网关(参见0.9.0.RELEASE版本的spring cloud alibaba nacos+gateway网关实 ...

  10. 【FreeMarker】FreeMarker快速入门(一)

    什么是 FreeMarker FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具. 它不是面向最终用户 ...