mybatis

 

mybatis

简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

官方地址:https://mybatis.org/mybatis-3/zh/index.html

springboot集成

详细参考:Spring boot Mybatis 整合(注解版)

  1. 添加依赖

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>${mybatis-spring-boot-starter.version}</version>
    </dependency>
    
  2. 配置 application.properties

    #mybatis config
    mybatis.mapper-locations=classpath:/mappers/**/*.xml
    # model 包名
    mybatis.type-aliases-package=com.xxx.model
    mybatis.configuration.map-underscore-to-camel-case=true
    mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
  3. 在代码中使用:

    在启动类添加包扫描(建议)或者在mapper文件添加@Mapper注解,使用的时候把mapper文件当作普通的类注入就可以了。

    //在启动类添加包扫描
    @MapperScan("com.xxx.mapper")
    public class XxxApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(XxxApplication.class, args);
    	}
    }
    
    //在mapper文件添加@Mapper注解
    @Mapper
    public interface XxxMapper {
    
        int deleteByPrimaryKey(Long id);
    
        int insert(Xxx record);
    
        int insertSelective(Xxx record);
    
        Xxx selectByPrimaryKey(Long id);
    
        int updateByPrimaryKeySelective(Xxx record);
    
        int updateByPrimaryKey(Xxx record);
    }
    
    

mybatis-generator

mybatis-generator是mybatis代码生成器,方便基于mysql表生成Mybatis适合的实体、Mapper接口和xml映射文件

mybatis generator详解:MyBatis Generator 详解

在MavenPom文件添加mybatis-generator-maven-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <configuration>
                <!--mybatis的代码生成器的配置文件-->
                <configurationFile>src/main/resources/generator-config.xml</configurationFile>
                <!--允许覆盖生成的文件-->
                <overwrite>true</overwrite>
                <verbose>true</verbose>
            </configuration>
            <dependencies>
                <!-- mysql的JDBC驱动 -->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>${mysql.version}</version>
                </dependency>
                <!--tk.mybatis 依赖,可选 -->
                <dependency>
                    <groupId>tk.mybatis</groupId>
                    <artifactId>mapper</artifactId>
                    <version>${tk.mapper.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    <plugins>
</build>

generator-config.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>

    <!-- 配置table表信息内容体,targetRuntime指定采用MyBatis3的版本 -->
    <context id="tables" targetRuntime="MyBatis3">

        <property name="javaFileEncoding" value="UTF-8"/>

        <!-- 抑制生成注释,由于生成的注释都是英文的,可以不让它生成 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!-- 配置数据库连接信息 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/cne_sys?characterEncoding=utf-8"
                        userId="root"
                        password="xxxxxxxx">
        </jdbcConnection>

        <!-- 生成model类,targetPackage指定model类的包名, targetProject指定生成的model放在哪个工程下面-->
        <javaModelGenerator targetPackage="com.xxx.model" targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
            <property name="trimStrings" value="false"/>
        </javaModelGenerator>

        <!-- 生成MyBatis的Mapper.xml文件,targetPackage指定mapper.xml文件的包名, targetProject指定生成的mapper.xml放在哪个工程下面 -->
        <sqlMapGenerator targetPackage="mappers" targetProject="src/main/resources">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 生成MyBatis的Mapper接口类文件,targetPackage指定Mapper接口类的包名, targetProject指定生成的Mapper接口放在哪个工程下面 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.xxx.mapper"
                             targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 数据库表名及对应的Java模型类名 -->

        <table tableName="tbl_user" domainObjectName="User" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"/>

    </context>
</generatorConfiguration>

MybatixX Idea 快捷开发插件

简介

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。说明:MybatisX快速开发插件

安装

安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。

功能

  • XML 跳转
  • 生成代码(需先在 idea 配置 Database 配置数据源)
  • 重置模板
  • JPA 提示

生成代码的模板配置

按照指定目录找到插件模板配置目录 Scratches and Consoles -> Extensions -> MybatisX 这里会提供默认模板: 例如在 1.4.13 提供了模板: default-all,default,mybatis-plus2,mybatis-plus3 如果想重置默认模板, 可以右键点击 MybatisX 目录,选择 Restore Default Extensions 选项

mybatisx-template-setting

自定义模板内容

名称 含义
tableClass.fullClassName 类的全称(包括包名)
tableClass.shortClassName 类的简称
tableClass.tableName 表名
tableClass.pkFields 表的所有主键字段
tableClass.allFields 表的所有字段
tableClass.baseFields 排除主键和 blob 的所有字段
tableClass.baseBlobFields 排除主键的所有字段
tableClass.remark 表注释

字段信息

名称 含义
field.fieldName 字段名称
field.columnName 列名称
field.jdbcType jdbc 类型
field.columnLength 列段长度
field.columnScale 列的精度
field.columnIsArray 字段类型是不是数组类型
field.shortTypeName java 类型短名称, 通常用于定义字段
field.fullTypeName java 类型的长名称, 通常用于导入
field.remark 字段注释
field.autoIncrement 是否自增
field.nullable 是否允许为空

配置信息

名称 含义
baseInfo.shortClassName 配置名称
baseInfo.tableName 配置文件名称
baseInfo.pkFields 配置名称
baseInfo.allFields 后缀
baseInfo.baseFields 包名
baseInfo.baseBlobFields 模板内容
baseInfo.remark 相对模块的资源文件路径

mybatis分页插件pageHelper

相关介绍如下

使用说明

  1. 添加依赖

    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>${pagehelper.version}</version>
    </dependency>
    
  2. 配置 application.properties

    # pageHelper分页插件配置
    pagehelper.helper-dialect=mysql
    pagehelper.reasonable=true
    pagehelper.support-methods-arguments=true
    pagehelper.params=countSql
    

    参数说明:

    分页插件可选参数如下:

    • dialect:默认情况下会使用 PageHelper 方式进行分页,如果想要实现自己的分页逻辑,可以实现 Dialect(com.github.pagehelper.Dialect) 接口,然后配置该属性为实现类的全限定名称。

    下面几个参数都是针对默认 dialect 情况下的参数。使用自定义 dialect 实现时,下面的参数没有任何作用。

    1. helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值: oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby 特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。 你也可以实现 AbstractHelperDialect,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。
    2. offsetAsPageNum:默认值为 false,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为 true 时,会将 RowBounds 中的 offset 参数当成 pageNum 使用,可以用页码和页面大小两个参数进行分页。
    3. rowBoundsWithCount:默认值为false,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为true时,使用 RowBounds 分页会进行 count 查询。
    4. pageSizeZero:默认值为 false,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。
    5. reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
    6. params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
    7. supportMethodsArguments:支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTestArgumentsObjTest
    8. autoRuntimeDialect:默认值为 false。设置为 true 时,允许在运行时根据多数据源自动识别对应方言的分页 (不支持自动选择sqlserver2012,只能使用sqlserver),用法和注意事项参考下面的场景五
    9. closeConn:默认值为 true。当使用运行时动态数据源或没有设置 helperDialect 属性自动获取数据库类型时,会自动获取一个数据库连接, 通过该属性来设置是否关闭获取的这个连接,默认true关闭,设置为 false 后,不会关闭获取的连接,这个参数的设置要根据自己选择的数据源来决定。
    10. aggregateFunctions(5.1.5+):默认为所有常见数据库的聚合函数,允许手动添加聚合函数(影响行数),所有以聚合函数开头的函数,在进行 count 转换时,会套一层。其他函数和列会被替换为 count(0),其中count列可以自己配置。
  3. 重要提示

    PageHelper.startPage方法重要提示

    只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询(Select)方法会被分页。

    请不要配置多个分页插件

    请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xmlSpring<bean>配置方式,请选择其中一种,不要同时配置多个分页插件)!

    分页插件不支持带有for update语句的分页

    对于带有for update的sql,会抛出运行时异常,对于这样的sql建议手动分页,毕竟这样的sql需要重视。

    分页插件不支持嵌套结果映射

    由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。

  4. 在代码中使用

    //第一种,RowBounds方式的调用
    List<User> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));
    
    //第二种,Mapper接口方式的调用,推荐这种使用方式。
    PageHelper.startPage(1, 10);
    List<User> list = userMapper.selectIf(1);
    
    //第三种,Mapper接口方式的调用,推荐这种使用方式。
    PageHelper.offsetPage(1, 10);
    List<User> list = userMapper.selectIf(1);
    
    //第四种,参数方法调用
    //存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
    public interface CountryMapper {
        List<User> selectByPageNumSize(
                @Param("user") User user,
                @Param("pageNum") int pageNum,
                @Param("pageSize") int pageSize);
    }
    //配置supportMethodsArguments=true
    //在代码中直接调用:
    List<User> list = userMapper.selectByPageNumSize(user, 1, 10);
    
    //第五种,参数对象
    //如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
    //有如下 User 对象
    public class User {
        //其他fields
        //下面两个参数名和 params 配置的名字一致
        private Integer pageNum;
        private Integer pageSize;
    }
    //存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
    public interface CountryMapper {
        List<User> selectByPageNumSize(User user);
    }
    //当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
    List<User> list = userMapper.selectByPageNumSize(user);
    
    //第六种,ISelect 接口方式
    //jdk6,7用法,创建接口
    Page<User> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {
        @Override
        public void doSelect() {
            userMapper.selectGroupBy();
        }
    });
    //jdk8 lambda用法
    Page<User> page = PageHelper.startPage(1, 10).doSelectPage(()-> userMapper.selectGroupBy());
    
    //也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
    pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {
        @Override
        public void doSelect() {
            userMapper.selectGroupBy();
        }
    });
    //对应的lambda用法
    pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> userMapper.selectGroupBy());
    
    //count查询,返回一个查询语句的count数
    long total = PageHelper.count(new ISelect() {
        @Override
        public void doSelect() {
            userMapper.selectLike(user);
        }
    });
    //lambda
    total = PageHelper.count(()->userMapper.selectLike(user));
    

    PageInfo说明:

    pageNum当前页
    pageSize每页的数量
    size当前页的数量
    orderBy排序
    startRow当前页面第一个元素在数据库中的行号
    endRow当前页面最后一个元素在数据库中的行号
    total总记录数(在这里也就是查询到的用户总数)
    pages总页数 (这个页数也很好算,每页5条,总共有11条,需要3页才可以显示完)
    list结果集
    prePage前一页
    nextPage下一页
    isFirstPage是否为第一页
    isLastPage是否为最后一页
    hasPreviousPage是否有前一页
    hasNextPage是否有下一页
    navigatePages导航页码数
    navigatepageNums所有导航页号
    navigateFirstPage导航第一页
    navigateLastPage导航最后一页
    firstPage第一页
    lastPage最后一页
    
  5. 实际例子,github示例

    // 相关配置
    mybatis:
        type-aliases-package: tk.mybatis.springboot.model
        mapper-locations: classpath:mapper/*.xml
    
    mapper:
        mappers:
            - tk.mybatis.springboot.util.MyMapper
        not-empty: false
        identity: MYSQL
    
    pagehelper:
        helperDialect: mysql
        reasonable: true
        supportMethodsArguments: true
        params: count=countSql
    
    **/
    // 关键代码如下,包括 controller,service,mapper
    // controller
    @RestController
    @RequestMapping("/users")
    public class UserInfoController {
    
        @Autowired
        private UserInfoService userInfoService;
    
        @RequestMapping
        public PageInfo<UserInfo> getAll(UserInfo userInfo) {
            List<UserInfo> userInfoList = userInfoService.getAll(userInfo);
            return new PageInfo<UserInfo>(userInfoList);
        }
    
        @RequestMapping(value = "/add")
        public UserInfo add() {
            return new UserInfo();
        }
        @RequestMapping(value = "/view/{id}")
        public UserInfo view(@PathVariable Integer id) {
            ModelAndView result = new ModelAndView();
            UserInfo userInfo = userInfoService.getById(id);
            return userInfo;
        }
    
        @RequestMapping(value = "/delete/{id}")
        public ModelMap delete(@PathVariable Integer id) {
            ModelMap result = new ModelMap();
            userInfoService.deleteById(id);
            result.put("msg", "删除成功!");
            return result;
        }
    
        @RequestMapping(value = "/save", method = RequestMethod.POST)
        public ModelMap save(UserInfo userInfo) {
            ModelMap result = new ModelMap();
            String msg = userInfo.getId() == null ? "新增成功!" : "更新成功!";
            userInfoService.save(userInfo);
            result.put("userInfo", userInfo);
            result.put("msg", msg);
            return result;
        }
    }
    /**
    * service
    */
    @Service
    public class UserInfoService {
    
        @Autowired
        private UserInfoMapper userInfoMapper;
    
        public List<UserInfo> getAll(UserInfo UserInfo) {
            if (UserInfo.getPage() != null && UserInfo.getRows() != null) {
                PageHelper.startPage(UserInfo.getPage(), UserInfo.getRows());
            }
            return userInfoMapper.selectAll();
        }
    
        public UserInfo getById(Integer id) {
            return userInfoMapper.selectByPrimaryKey(id);
        }
    
        public void deleteById(Integer id) {
            userInfoMapper.deleteByPrimaryKey(id);
        }
    
        public void save(UserInfo country) {
            if (country.getId() != null) {
                userInfoMapper.updateByPrimaryKey(country);
            } else {
                userInfoMapper.insert(country);
            }
        }
    }
    
    /**
    * mapper user tk.mybatis
    */
    public interface UserInfoMapper extends MyMapper<UserInfo> {
    }
    
    
    
    
    

通用Mapper

TK通用Mapper和Mybatis-Plus使用对比:TK通用Mapper和Mybatis-Plus使用对比

mybatisPlus

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

官方地址:https://baomidou.com/

tkmybatis

tkmybatis 是对底层 sql 进行了抽象封装,不需要考虑 sql 怎么写,只需要按照逻辑思维,遵循 tkmybatis 的语法即可实现数据库操作。

tkmybatis详细教程