Hey, Nice to meet You. 

有过人之节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,必

Mybatis3详解(十三)----Mybatis逆向工程

 


1、什么是逆向工程

Mybatis的逆向工程就是由代码生成器生成我们需要的代码和映射文件。我们在编写Mybatis程序时,基本都是围绕着pojo类,Mapper接口,Mapper.xml文件等文件来进行的。如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的pojo类,Mapper接口,Mapper.xml文件,这显然需要花费巨大的精力,而且可能由于表字段太多,哪里写错了都难以排除。所以我们在实际开发中,一般使用逆向工程方式来自动生成所需的文件,这也是企业中一种非常常见的方法。

注意:在使用逆向工程生成代码文件的时候,最好额外创建一个项目,不要在原来的项目中使用,因为如果你在原项目中有相同名字的文件,那么就会被新生成的文件所覆盖,导致之前写的代码没了,有一定的风险。所以实际开发中,我们一般新建一个项目,然后将生成的文件复制到自己的所需的工程中。

2、逆向工程生成代码

①、首先创建maven项目

项目整体目录:

image

导入maven依赖:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- 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

01
02
03
04
05
06
07
08
# 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配置文件

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?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中的 & 要改成转义字符 &amp; 这里传上来页面自动给转成了 &。

image

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

脑壳痛 (1)

 

④、创建逆向工程核心生成代码GeneratorSql.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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();
        }
    }
 
}

⑤、运行逆向工程核心生成代码

       运行上面的程序,如果控制台打印了如下日志,说明生成代码成功了。

image

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

image

下面我们就来学习如何使用它们。

3、逆向工程举例

首先我们将上面生成的文件复制到目标项目中。在使用逆向工程举例之前,先来介绍生成的文件有哪些东西:

(1)、TUserMapper接口生成的方法介绍:

  1. long countByExample(TUserExample example):按条件计数
  2. int deleteByExample(TUserExample example):按条件删除
  3. int deleteByPrimaryKey(Integer id):按主键删除
  4. int insert(TUser record):插入数据(返回值为ID)
  5. int insertSelective(TUser record):插入数据,只插入值不为null的字段,内部动态sql判断
  6. List<TUser> selectByExample(TUserExample example):按条件查询,传入null表示查询所有
  7. TUser selectByPrimaryKey(Integer id):按主键查询
  8. int updateByExampleSelective(@Param("record") TUser record, @Param("example") TUserExample example):按条件更新值不为null的字段
  9. int updateByExample(@Param("record") TUser record, @Param("example") TUserExample example):按条件更新
  10. int updateByPrimaryKeySelective(TUser record):按主键更新值不为null的字段
  11. int updateByPrimaryKey(TUser record):按主键更新

测试不带条件的方法:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//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。

image

简单举例:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//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类,但如果自己多举几个例子也不难。    

posted @   唐浩荣  阅读(5015)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
点击右上角即可分享
微信分享提示

目录导航