mybatis的使用及源码分析(二) mybatis添加generator插件

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&amp;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();
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: MyBatis Generator件是一个自动生成MyBatis代码的工具,它可以根据数据库表结构自动生成对应的Java实体类、Mapper接口和XML映射文件。使用件可以大大提高开发效率,减少手写代码的工作量。同时,该件还支持自定义生成规则和件扩展,可以满足不同项目的需求。 ### 回答2: MyBatis Generator件是一个用于生成MyBatis持久层代码的工具。它通过读取数据库表结构信息,自动生成对应的实体类、Mapper接口以及XML映射文件。 该件的核心功能是根据数据库表结构生成对应的实体类。它会根据表的字段类型和命名规则,自动创建实体类的属性和对应的getter和setter方法。这样可以大大简化实体类的编写工作,提高开发效率。 除了实体类,件还会生成Mapper接口和XML映射文件。Mapper接口定义了数据库操作的方法,而XML映射文件提供了数据库操作的具体实现。这样,在使用MyBatis时,我们只需要编写Mapper接口的方法,而不需要手动编写SQL语句,MyBatis Generator会帮助我们自动生成。 件还提供了一些配置选项,可以根据需要进行个性化设置。我们可以指定生成的代码的包名、文件保存路径等信息。另外,件还支持自定义模板,可以根据需求修改生成代码的样式。 总之,MyBatis Generator件是一个非常实用的工具,可以大大简化MyBatis代码的编写工作。它通过自动生成实体类、Mapper接口和XML映射文件,提高了开发效率,减少了出错的可能性。它的灵活配置和自定义模板功能,还可以满足开发者个性化的需求。 ### 回答3: MyBatis Generator是一个开的代码生成工具,它可以根据数据库表结构自动生成对应的Java模型对象、Mapper接口和XML映射文件。 MyBatis Generator使用了类似于MyBatis的SQL映射语言来生成代码,用户只需编写一个名为"generatorConfig.xml"的配置文件,指定数据库连接信息、要生成代码的表信息以及代码生成的目标路径等,然后运行Generator的主类即可。 MyBatis Generator在代码生成过程中,会自动生成对应的Java POJO(Plain Old Java Object)类,该类与数据库表的字段一一对应,方便了与数据库的交互操作。同时,它也会生成Mapper接口,其中包含了常见的增删改查操作的方法,开发者可以直接调用这些方法来操作数据库。此外,MyBatis Generator还会生成XML映射文件,这个文件定义了SQL语句与Java方法的对应关系,方便了执行数据库操作。 MyBatis Generator件的优点是节省了开发人员大量手写重复代码的时间,提高了开发效率。它还遵循了MyBatis的设计哲学,减少了代码的冗余和复杂性。另外,MyBatis Generator可以与其他代码生成件配合使用,例如Spring Boot的Generator件,可以进一步简化开发工作。 总结来说,MyBatis Generator件是一个方便且高效的代码生成工具,它能够根据数据库表结构自动生成与数据库交互所需的Java模型对象、Mapper接口和XML映射文件,大大减少了开发人员的工作量,并提高了代码的可维护性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值