zoukankan      html  css  js  c++  java
  • Mybatis3详解(十三)——Mybatis逆向工程

    1、什么是逆向工程

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

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

    2、逆向工程生成代码

           ①、首先创建maven项目

           项目整体目录:

    image

           导入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
    


           ③、创建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表为例,可以写多个 -->
            <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

    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):按主键更新

          测试不带条件的方法:

    //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

           简单举例:

    //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类,但如果自己多举几个例子也不难。    

  • 相关阅读:
    函数传参的方式
    统计一个文本中单词频次最高的 10 个单词?
    统计一个文本中单词频次最高的 10 个单词?
    python每日练习0801
    关键字驱动小练习
    Fiddler抓包从入门到不放弃
    pycharm2019.1.3激活方法--激活码可以用到2089年
    Selenium+Python调Chrome浏览器时报Traceback (most recent call last): File "C:/Users/EDZ/Desktop/selenium_demo/demo001.py", line 12, in <module>
    JMeter服务端压测,人人都会的小白版本
    XShell命令大全
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/14013584.html
Copyright © 2011-2022 走看看