MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器。它将为所有版本的MyBatis以及版本2.2.0之后的iBATIS版本生成代码。它将内省数据库表(或许多表),并将生成可用于访问表的工件。这减少了设置对象和配置文件以与数据库表交互的初始麻烦。MBG寻求对简单CRUD(创建,检索,更新,删除)的大部分数据库操作产生重大影响。您仍然需要为连接查询或存储过程手动编写SQL和对象代码。
MyBatis Generator将生成:
与表结构匹配的Java POJO。这可能包括:
-
一个匹配表的主键的类(如果有主键)
-
一个匹配表的非主键字段的类(BLOB字段除外)
-
包含表的BLOB字段的类(如果表具有BLOB字段)
-
用于启用动态选择,更新和删除的类
这些类之间存在适当的继承关系。请注意,生成器可以配置为生成不同类型的POJO层次结构 - 例如,如果 您愿意,可以选择为每个表生成单个域对象。
MyBatis / iBATIS兼容的SQL Map XML文件。MBG在配置中的每个表上为简单的CRUD函数生成SQL。生成的SQL语句包括:
- 插入
- 按主键更新
- 通过示例更新(使用动态where子句)
- 按主键删除
- 按示例删除(使用动态where子句)
- 按主键查询
- 按示例查询(使用动态where子句)
根据表的结构,这些语句有不同的变体(例如,如果表没有主键,则MBG不会通过主键功能生成更新)。
适当使用上述对象的Java客户端类。Java客户端类的生成是可选的。MBG将为MyBatis 3.x生成以下类型的
Java客户端:适用于MyBatis 3.x映射器基础结构的映射器接口。
MyBatis生成器设计在迭代开发环境中运行良好,并且可以作为Ant任务或Maven插件包含在连续构建环境中。运行MBG时需要注意的重要事项包括:
- 如果存在与新生成的XML文件同名的现有文件,MBG将自动合并XML文件。MBG不会覆盖您对其生成的XML文件所做的任何自定义更改。您可以反复运行它,而不必担心会丢失对XML的自定义更改。MBG将替换先前运行中生成的任何XML元素。
- MBG 不会合并Java文件,它可以覆盖现有文件或使用不同的唯一名称保存新生成的文件。如果对生成的Java文件进行更改并以迭代方式运行MBG,则必须手动合并更改。当作为Eclipse 插件运行时 ,MBG可以自动合并Java文件
mybatis-generator官方地址:https://github.com/mybatis/generator/releases
mybatis-generator文档地址:http://www.mybatis.org/generator/index.html
本文项目搭建地址:https://github.com/zhuquanwen/mybatis-learn/releases/tag/with-generator
搭建过程:
在上一篇文章基础上搭建,有些过程不详细描述,源码在上一篇已附上,参见上一篇:https://blog.csdn.net/u011943534/article/details/104706455
项目结构:
1、引入mybatis-generator依赖
在pom.xml中添加依赖
<!-- mybatis-generator -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
添加编译时资源编译方式,把src/main/java下xml文件也编译
<build>
...
<resources>
<!--编译src/main/java目录下的xml文件-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2、导入测试的sql
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50722
Source Host : localhost:3306
Source Database : mybatis_learn
Target Server Type : MYSQL
Target Server Version : 50722
File Encoding : 65001
Date: 2020-03-07 15:47:03
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`real_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', 'zhangsan', '张三');
INSERT INTO `student` VALUES ('2', 'lisi', '李四');
INSERT INTO `student` VALUES ('3', 'wangwu', '王五');
3、resources下编写代码生成器配置XML文件generatorConfig.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>
<!-- context指定环境 -->
<context id="MyGererator" targetRuntime="MyBatis3">
<!-- 这个标签可以去掉各类元素生成的注释,默认是全部生成的 -->
<commentGenerator>
<!-- 去掉注释 -->
<property name="suppressAllComments" value="true"/>
<!-- 去掉时间戳 -->
<property name="suppressDate" value="true"/>
</commentGenerator>
<!-- 数据库连接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_learn?useUnicode=true&characterEncoding=utf8"
userId="root"
password="root">
</jdbcConnection>
<!-- JAVA JDBC数据类型转换,可以参照官方文档 -->
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- javaModelGenerator javaBean配置
targetPackage 输入包名 输出路径
targetProject 输出项目位置 -->
<javaModelGenerator targetPackage="com.learn.zqw.generator.domain" targetProject="src/main/java">
<!-- enableSubPackages 是否开启子包名称 是否在包名后边加上scheme名称 -->
<property name="enableSubPackages" value="false" />
<!-- 在Set方法中加入.trim -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 映射文件mapper.xml配置 -->
<sqlMapGenerator targetPackage="com.learn.zqw.generator.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- 动态代理类接口,和mapper.xml在要同一个路径 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.learn.zqw.generator.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 数据表 根据数据库中的表来生成 -->
<table tableName="student"/>
<!-- 数据表更详细的属性参见官方文档,也可参照https://www.jianshu.com/p/e09d2370b796,里注释掉-->
<!-- <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" >
<property name="useActualColumnNames" value="true"/>
<generatedKey column="ID" sqlStatement="DB2" identity="true" />
<columnOverride column="DATE_FIELD" property="startDate" />
<ignoreColumn column="FRED" />
<columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
</table> -->
</context>
</generatorConfiguration>
如上面的配置,都已经在注释中作了说明,更多配置可参考:https://www.jianshu.com/p/e09d2370b796
4、编写代码生成器主类
package com.learn.zqw.generator;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* //TODO
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/3/7 15:43
* @since jdk1.8
*/
public class Generator {
public static void main(String[] args) throws IOException, XMLParserException,
InvalidConfigurationException, SQLException, InterruptedException {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("E:\\coding\\idea\\project\\mybatis-learn\\src\\main\\resources\\generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
上面代码中的路径为配置的代码生成器配置XML的路径
5、运行生成器
运行生成器,在配置文件配置的包下自动生成Student.java、StudentExample.java、StudentMapper.java、StudentMapper.xml
,其中Student.java为实体,StudentExample.java为一些条件操作的帮助类,StudentMapper.java为数据接口,StudentMapper.xml为SQL定义文件。
修改Student.java,去除get、set方法,并添加lombok注解。
package com.learn.zqw.generator.domain;
import lombok.Data;
@Data
public class Student {
private Integer id;
private String name;
private String realName;
}
注意多次运行生成器会引起xml文件重叠,其他文件也会覆盖一些已修改的内容,可以先配置一个临时路径,再拷贝到真实路径下
6、增加分页支持(可选)
可在后面的测试中看到分页的效果
修改StudentMapper.xml再orderByClause下添加分页支持
<if test="orderByClause != null">
order by ${orderByClause}
</if>
<if test="limit != null">
limit ${limit}
</if>
在StudentExample.java中添加属性limit,并生成get、set方法
protected String limit;
7、在SqlMapConfig.xml中添加StudentMapper.xml的配置
<mappers>
<mapper resource="com/learn/zqw/IUserMapper.xml" />
<mapper resource="com/learn/zqw/generator/mapper/StudentMapper.xml" />
</mappers>
8、测试各类数据库操作接口
代码中已做了注释
package com.learn.zqw.generator;
import com.learn.zqw.generator.domain.Student;
import com.learn.zqw.generator.domain.StudentExample;
import com.learn.zqw.generator.mapper.StudentMapper;
import lombok.Cleanup;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
* //TODO
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/3/7 15:49
* @since jdk1.8
*/
@RunWith(JUnit4.class)
public class GeneratorTests {
/**
* 测试按照ID查询
* */
@Test
public void Test1() throws IOException {
//1.读取配置文件
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
//2. 创建SqlSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
//按主键查询
Student student = mapper.selectByPrimaryKey(1);
Assert.assertNotNull(student);
System.out.println(student);
}
/**
* 使用Example查询
* */
@Test
public void Test2() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
//将条件封装到createCriteria集合中 -条件列表
example.createCriteria().andNameEqualTo("zhangsan").andRealNameIsNotNull();
//按条件查询
List<Student> list = mapper.selectByExample(example);
System.out.println("按条件查询:");
Assert.assertNotNull(list);
list.forEach(System.out::println);
}
/**
* 测试条件插入
* */
@Test
public void Test3() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student() ;
student.setName(UUID.randomUUID().toString());
int i = mapper.insertSelective(student);
session.commit();
Assert.assertEquals(1, i);
}
/**
* 按照Example求条目
* */
@Test
public void Test4() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
example.createCriteria().andIdBetween(1, 200).andNameIn(Arrays.asList("zhangsan", "lisi"));
long l = mapper.countByExample(example);
Assert.assertEquals(2, l);
}
/**
* 测试按照Example删除
* */
@Test
public void Test5() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student();
String name = UUID.randomUUID().toString();
student.setName(name);
mapper.insertSelective(student);
session.commit();
StudentExample example = new StudentExample();
example.createCriteria().andNameEqualTo(name);
int i = mapper.deleteByExample(example);
Assert.assertEquals(1, i);
session.commit();
}
/**
* 测试按照ID删除
* */
@Test
public void Test6() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student();
String name = UUID.randomUUID().toString();
student.setName(name);
student.setId(1001);
mapper.insertSelective(student);
session.commit();
StudentExample example = new StudentExample();
example.createCriteria().andNameEqualTo(name);
int i = mapper.deleteByPrimaryKey(1001);
Assert.assertEquals(1, i);
session.commit();
}
/**
* 测试普通插入
* */
@Test
public void Test7() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setName(UUID.randomUUID().toString());
student.setRealName("测试名字");
mapper.insert(student);
session.commit();
}
/**
* 测试条件修改,并使用example
* */
@Test
public void Test8() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setRealName("测试名字");
StudentExample example = new StudentExample();
example.createCriteria().andIdGreaterThan(3);
mapper.updateByExampleSelective(student, example);
session.commit();
}
/**
* 测试普通修改,并使用example
* */
@Test
public void Test9() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
example.createCriteria().andIdGreaterThan(100);
List<Student> students = mapper.selectByExample(example);
Student student = students.get(0);
student.setRealName("测试名字22");
mapper.updateByExample(student, example);
session.commit();
}
/**
* 测试条件修改,并使用Id
* */
@Test
public void Test10() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
example.createCriteria().andIdGreaterThan(100);
List<Student> students = mapper.selectByExample(example);
Student student = students.get(0);
student.setRealName("测试名字33");
mapper.updateByPrimaryKeySelective(student);
session.commit();
}
/**
* 测试普通修改,并使用Id
* */
@Test
public void Test11() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
example.createCriteria().andIdGreaterThan(100);
List<Student> students = mapper.selectByExample(example);
Student student = students.get(0);
student.setRealName(null);
mapper.updateByPrimaryKey(student);
session.commit();
}
/**
* 测试查询并排序
* */
@Test
public void Test12() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
example.createCriteria().andIdGreaterThan(0);
example.setOrderByClause("name asc");
List<Student> students = mapper.selectByExample(example);
students.forEach(System.out::println);
session.commit();
}
/**
* 测试自定义的排序
* */
@Test
public void Test13() throws IOException {
@Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
example.createCriteria().andIdGreaterThan(0);
example.setOrderByClause("name asc");
example.setLimit("0, 3");
List<Student> students = mapper.selectByExample(example);
students.forEach(System.out::println);
session.commit();
}
}