Mybatis3详解(十三)----Mybatis逆向工程
1、什么是逆向工程
Mybatis的逆向工程就是由代码生成器生成我们需要的代码和映射文件。我们在编写Mybatis程序时,基本都是围绕着pojo类,Mapper接口,Mapper.xml文件等文件来进行的。如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的pojo类,Mapper接口,Mapper.xml文件,这显然需要花费巨大的精力,而且可能由于表字段太多,哪里写错了都难以排除。所以我们在实际开发中,一般使用逆向工程方式来自动生成所需的文件,这也是企业中一种非常常见的方法。
注意:在使用逆向工程生成代码文件的时候,最好额外创建一个项目,不要在原来的项目中使用,因为如果你在原项目中有相同名字的文件,那么就会被新生成的文件所覆盖,导致之前写的代码没了,有一定的风险。所以实际开发中,我们一般新建一个项目,然后将生成的文件复制到自己的所需的工程中。
2、逆向工程生成代码
①、首先创建maven项目
项目整体目录:

导入maven依赖:
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 逆向工程 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
②、创建日志文件log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
③、创建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>
<!--targetRuntime="MyBatis3Simple"表示生成简易版本,这里创建原始版本,参数为MyBatis3-->
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释。true:是;false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8"
userId="root"
password="root">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL和NUMERIC类型解析为Integer,为true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:POJO类生成的位置 -->
<javaModelGenerator targetPackage="com.thr.pojo"
targetProject="./src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.thr.mapper"
targetProject="./src/main/resources">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.thr.mapper"
targetProject="./src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定生成哪些数据库表,要和数据库中对应,不能写错了,这里以t_user表为例,可以写多个;domainObjectName是要生成的实体类名称-->
<table schema="mybatis" tableName="t_user"/>
<!-- 有些表的字段需要指定java类型
<table schema="" tableName="">
<columnOverride column="" javaType="" />
</table> -->
</context>
</generatorConfiguration>
注意:serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8中的 & 要改成转义字符 & 这里传上来页面自动给转成了 &。

还有就是不同的数据库中不能含有相同的表,例如数据库A有t_user表,数据库B也有t_user表,那么到时候代码不知道生成哪个,而我恰好生成的是我们不需要的那个。啊?你说上面不是指定了数据库吗,怎么会到读取到其它数据库的表,不好意思,我试了不下十遍,最后我把其它数据库同名的表删除才成功的。如果你没有这种情况那更好咯。

④、创建逆向工程核心生成代码GeneratorSql.java
package com.thr.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.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 逆向工程核心生成代码
*/
public class GeneratorSql {
public void generator() throws Exception {
List<String> warnings = new ArrayList<>();
boolean overwrite = true;
// 指定逆向工程配置文件
String file = GeneratorSql.class.getResource("/generatorConfig.xml").getFile();
File configFile = new File(file);
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);
}
// 执行main方法以生成代码
public static void main(String[] args) {
try {
GeneratorSql generatorSql = new GeneratorSql();
generatorSql.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
⑤、运行逆向工程核心生成代码
运行上面的程序,如果控制台打印了如下日志,说明生成代码成功了。

然后我们再看项目就会发现生成了如下文件:

下面我们就来学习如何使用它们。
3、逆向工程举例
首先我们将上面生成的文件复制到目标项目中。在使用逆向工程举例之前,先来介绍生成的文件有哪些东西:
(1)、TUserMapper接口生成的方法介绍:
- long countByExample(TUserExample example):按条件计数
- int deleteByExample(TUserExample example):按条件删除
- int deleteByPrimaryKey(Integer id):按主键删除
- int insert(TUser record):插入数据(返回值为ID)
- int insertSelective(TUser record):插入数据,只插入值不为null的字段,内部动态sql判断
- List<TUser> selectByExample(TUserExample example):按条件查询,传入null表示查询所有
- TUser selectByPrimaryKey(Integer id):按主键查询
- int updateByExampleSelective(@Param("record") TUser record, @Param("example") TUserExample example):按条件更新值不为null的字段
- int updateByExample(@Param("record") TUser record, @Param("example") TUserExample example):按条件更新
- int updateByPrimaryKeySelective(TUser record):按主键更新值不为null的字段
- int updateByPrimaryKey(TUser record):按主键更新
测试不带条件的方法:
//Mybatis的测试
public class MybatisTest {
//定义 SqlSession
private SqlSession sqlSession = null;
//定义 TUserMapper对象
private TUserMapper mapper = null;
@Before//在测试方法执行之前执行
public void getSqlSession(){
//1、加载 mybatis 全局配置文件
InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3、根据 sqlSessionFactory 产生session
sqlSession = sqlSessionFactory.openSession();
//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成TUserMapper的代理实现类
mapper = sqlSession.getMapper(TUserMapper.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
}
//查询所有用户信息
@Test
public void selectAllUser(){
List<TUser> tUsers = mapper.selectByExample(null);//传入null表示查询所有
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//根据用户id查询用户
@Test
public void selectByUserId(){
TUser tUser = mapper.selectByPrimaryKey(1);
System.out.println(tUser);
}
//添加用户信息
@Test
public void insertUser(){
TUser tUser = new TUser();
tUser.setUsername("凡尔赛");
tUser.setAge(18);
tUser.setBirthday(new Date());
tUser.setSex("0");
tUser.setAddress("漂亮国");
int i = mapper.insertSelective(tUser);
System.out.println(i>0?"添加成功":"添加失败");
}
//更新用户信息
@Test
public void updateUser(){
TUser tUser = new TUser();
tUser.setId(8);//这里要设置id才能修改成功,否则不知道修改哪一条数据
tUser.setUsername("川建国");
tUser.setAge(50);
tUser.setBirthday(new Date());
tUser.setSex("1");
tUser.setAddress("漂亮国");
int i = mapper.updateByPrimaryKeySelective(tUser);
System.out.println(i>0?"修改成功":"修改失败");
}
//删除用户信息
@Test
public void deleteUser(){
int i = mapper.deleteByPrimaryKey(8);
System.out.println(i>0?"删除成功":"删除失败");
}
}
(2)、TUserExample条件扩展类介绍:
上面的测试方法是不带条件的操作,那么接下来学习一下按条件如何进行增删改查操作,我们在逆向工程中已经生成了这个类TUserExample,这个类就是一个条件扩展类,里面定义了一系列方法用来做条件,比如:排序、去重、大于、小于、等于、模糊查询、数据在某某之间等等。
我们在TUserExample类中可以看到定义了一个内部类GeneratedCriteria,这个内部类就定义了一系列条件的方法,这些条件最后都会拼接在SQL中,但是我们一般不用它,都用它的子类Criteria来进行操作,Criteria继承了内部类GeneratedCriteria。

简单举例:
//Mybatis的测试
public class MybatisTest1 {
//定义 SqlSession
private SqlSession sqlSession = null;
//定义 UserMapper对象
private TUserMapper mapper = null;
@Before//在测试方法执行之前执行
public void getSqlSession(){
//1、加载 mybatis 全局配置文件
InputStream is = MybatisTest1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3、根据 sqlSessionFactory 产生session
sqlSession = sqlSessionFactory.openSession();
//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类
mapper = sqlSession.getMapper(TUserMapper.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
}
//模糊查询用户信息
@Test
public void selectUserLike(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria = example.createCriteria();
//模糊条件
criteria.andUsernameLike("%三%");
/*sql语句相当于:select id, username, age, birthday, sex, address
from t_user WHERE ( username like ? )*/
List<TUser> tUsers = mapper.selectByExample(example);
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//查询年龄在18-30岁之间的用户信息
@Test
public void selectUserBetween(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria = example.createCriteria();
//Between条件
criteria.andAgeBetween(18,30);
example.or(criteria);
example.setDistinct(true);
/*sql语句相当于:select distinct id, username, age, birthday, sex, address
from t_user WHERE ( age between ? and ? ) or( age between ? and ? )*/
List<TUser> tUsers = mapper.selectByExample(example);
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//查询用户名A或B
@Test
public void selectUserOr(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria1 = example.createCriteria();
criteria1.andUsernameEqualTo("黄飞鸿");
TUserExample.Criteria criteria2 = example.createCriteria();
criteria2.andUsernameEqualTo("马保国");
//将criteria2条件拼接在 or 关键字字后面
example.or(criteria2);
/*sql语句相当于:select id, username, age, birthday, sex, address
from t_user WHERE ( username = ? ) or( username = ? )*/
List<TUser> tUsers = mapper.selectByExample(example);
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//根据用户名删除用户
@Test
public void deleteUserExample(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("凡尔赛");
//sql语句相当于:delete from t_user WHERE ( username = ? )
int i = mapper.deleteByExample(example);
System.out.println(i>0?"删除成功":"删除失败");
}
}
至此Mybatis的逆向工程就全部介绍完成了,说难也不是特别难,只要一步步自己去实现,去理解一遍,是非常简单的,可能复杂一点的是那个XxxExample类,但如果自己多举几个例子也不难。
浙公网安备 33010602011771号