MyBatis-最佳实践2

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MyBatis-最佳实践2

4.分页操作


4.1 逻辑分页


MyBatis里面有一个逻辑分页对象RowBounds,里面主要有两个属性,offset和limit(从第几条开始,查询多少条)。我们可以在Mapper接口的方法上加上这个参数,不需要修改xml里面的SQL语句。
复制代码



接口中定义

public List<User> queryUserList(RowBounds rowBounds);
复制代码



测试类

@Test
    public void test01() throws Exception{
        init();
        UserMapper mapper = session.getMapper(UserMapper.class);
        // 设置分页的数据
        RowBounds rowBounds = new RowBounds(1,3);
        List<User> users = mapper.queryUserList(rowBounds);
        for (User user : users) {
            System.out.println(user);
        }
    }
复制代码


RowBounds的工作原理其实是对ResultSet的处理。它会舍弃掉前面offset条数据,然后再取剩下的数据的limit条。
复制代码


// DefaultResultSetHandler.java
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
   DefaultResultContext<Object> resultContext = new DefaultResultContext();
   ResultSet resultSet = rsw.getResultSet();
   this.skipRows(resultSet, rowBounds);
   while(this.shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
       ResultMap discriminatedResultMap = this.resolveDiscriminatedResultMap(resultSet, resultMap, (String)null);
       Object rowValue = this.getRowValue(rsw, discriminatedResultMap, (String)null);
       this.storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
  }
}
复制代码


很明显,如果数据量大的话,这种翻页方式效率会很低(跟查询到内存中再使用subList(start,end)没什么区别)。所以我们要用到物理翻页。



4.2 物理分页


物理翻页是真正的翻页,它是通过数据库支持的语句来翻页。


第一种简单的办法就是传入参数(或者包装一个page对象),在SQL语句中翻页。


<select id="selectUserPage" parameterType="map" resultMap="BaseResultMap">
  select * from t_user limit #{curIndex} , #{pageSize}
</select>
复制代码


第一个问题是我们要在Java业务代码里面去计算起止序号;第二个问题是:每个需要翻页的Statement都要编写limit语句,会造成Mapper映射器里面很多代码冗余。


那我们就需要一种通用的方式,不需要去修改配置的任何一条SQL语句,我们只要传入当前是第几页,每页多少条就可以了,自动计算出来起止序号。


我们最常用的做法就是使用翻页的插件,比如PageHelper。


// pageSize每一页几条
PageHelper.startPage(pn, 10);
List<Employee> emps = employeeService.getAll();
// navigatePages 导航页码数
PageInfo page = new PageInfo(emps, 10);
return Msg.success().add("pageInfo", page);
复制代码


PageHelper是通过MyBatis的拦截器实现的,插件的具体原理我们后面的课再分析。


简单地来说,它会根据PageHelper的参数,改写我们的SQL语句。比如MySQL会生成limit语句,Oracle会生成rownum语句,SQL Server会生成top语句。




5.MBG与Example


https://github.com/mybatis/generator
复制代码


我们在项目中使用MyBaits的时候,针对需要操作的一张表,需要创建实体类、Mapper映射器、Mapper接口,里面又有很多的字段和方法的配置,这部分的工作是非常繁琐的。而大部分时候我们对于表的基本操作是相同的,比如根据主键查询、根据Map查询、单条插入、批量插入、根据主键删除等等等等。当我们的表很多的时候,意味着有大量的重复工作。
复制代码


所以有没有一种办法,可以根据我们的表,自动生成实体类、Mapper映射器、Mapper接口,里面包含了我们需要用到的这些基本方法和SQL呢?
复制代码


MyBatis也提供了一个代码生成器,叫做MyBatis Generator,简称MBG(它是MyBatis的一个插件)。我们只需要修改一个配置文件,使用相关的jar包命令或者Java代码就可以帮助我们生成实体类、映射器和接口文件。
复制代码


MBG的配置文件里面有一个Example的开关,这个东西用来构造复杂的筛选条件的,换句话说就是根据我们的代码去生成where条件。
复制代码


原理:在实体类中包含了两个有继承关系的Criteria,用其中自动生成的方法来构建查询条件。把这个包含了Criteria的实体类作为参数传到查询参数中,在解析Mapper映射器的时候会转换成SQL条件。
复制代码




5.1 添加配置文件


我们添加如下的配置文件
复制代码


<?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>
    <!-- 数据库的驱动包路径 -->
    <classPathEntry location="C:\Users\dpb\.m2\repository\mysql\mysql-connector-java\8.0.11\mysql-connector-java-8.0.11.jar" />
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!-- 去掉生成文件中的注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!-- 数据库链接URL、用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf-8&serverTimezone=UTC"
                        userId="root"
                        password="123456">
            <property name="nullCatalogMeansCurrent" value="true" />
        </jdbcConnection>
        <!-- <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver"
              connectionURL="jdbc:oracle:thin:@localhost:1521:XE"
              userId="car"
              password="car">
      </jdbcConnection>  -->
        <javaTypeResolver >
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>
        <!-- 生成模型的包名和位置 -->
        <javaModelGenerator targetPackage="com.boge.vip.domain" targetProject="./src/main/java">
            <!-- 是否在当前路径下新加一层schema,eg:fase路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
            <property name="enableSubPackages" value="false" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- 生成的映射文件包名和位置 -->
        <sqlMapGenerator targetPackage="com.boge.vip.mapper"  targetProject="./src/main/java">
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.boge.vip.mapper"  targetProject="./src/main/java">
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <table  tableName="t_user" domainObjectName="User"   />
    </context>
</generatorConfiguration>
复制代码



5.2 添加插件


我们需要在pom.xml中添加对应的插件
复制代码


<build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <!-- 指定配置文件的位置 -->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                </configuration>
            </plugin>
        </plugins>
    </build>
复制代码



5.3 生成


然后我们就可以利用插件帮助我们快速生成我们需要的表结构对应的相关文件
复制代码

image.png



6. 通用Mapper


问题:当我们的表字段发生变化的时候,我们需要修改实体类和Mapper文件定义的字段和方法。如果是增量维护,那么一个个文件去修改。如果是全量替换,我们还要去对比用MBG生成的文件。字段变动一次就要修改一次,维护起来非常麻烦。
复制代码



6.1 方式一


第一个,因为MyBatis的Mapper是支持继承的(见:https://github.com/mybatis/mybatis-3/issues/35)。所以我们可以把我们的Mapper.xml和Mapper接口都分成两个文件。一个是MBG生成的,这部分是固定不变的。然后创建DAO类继承生成的接口,变化的部分就在DAO里面维护。
复制代码


public interface UserMapperExt extends UserMapper {
    public List<User> selectUserByName(String userName);
}
复制代码


对应的映射文件


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.boge.vip.mapper.UserMapperExt" >
  <resultMap id="BaseResultMapExt" type="com.boge.vip.domain.User" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="user_name" property="userName" jdbcType="VARCHAR" />
    <result column="real_name" property="realName" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="age" property="age" jdbcType="INTEGER" />
    <result column="d_id" property="dId" jdbcType="INTEGER" />
    <result column="i_id" property="iId" jdbcType="INTEGER" />
  </resultMap>
  <select id="selectUserByName" resultMap="BaseResultMapExt" >
    select * from t_user where user_name = #{userName}
  </select>
</mapper>
复制代码



在全局配置文件中我们也需要扫描


<mappers>
        <mapper resource="mapper/UserMapper.xml"/>
        <mapper resource="mapper/UserMapperExt.xml"/>
    </mappers>
复制代码



所以以后只要修改Ext的文件就可以了。这么做有一个缺点,就是文件会增多。

image.png


6.2 方式二


既然针对每张表生成的基本方法都是一样的,也就是公共的方法部分代码都是一样的,我们能不能把这部分合并成一个文件,让它支持泛型呢?
复制代码


当然可以!


编写一个支持泛型的通用接口,比如叫GPBaseMapper
复制代码


,把实体类作为参数传入。这个接口里面定义了大量的增删改查的基础方法,这些方法都是支持泛型的。


自定义的Mapper接口继承该通用接口,例如BlogMapper extends GPBaseMapper
复制代码


,自动获得对实体类的操作方法。遇到没有的方法,我们依然可以在我们自己的Mapper里面编写。


我们能想到的解决方案,早就有人做了这个事了,这个东西就叫做通用Mapper。
复制代码


github.com/abel533/Map…

用途:主要解决单表的增删改查问题,并不适用于多表关联查询的场景。


除了配置文件变动的问题之外,通用Mapper还可以解决:


  1. 每个Mapper接口中大量的重复方法的定义;


  1. 屏蔽数据库的差异;


  1. 提供批量操作的方法;


  1. 实现分页。


使用方式:在Spring中使用时,引入jar包,替换applicationContext.xml中的sqlSessionFactory和configure。



<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
   <property name="basePackage" value="com.boge.crud.dao"/>
</bean>
复制代码




7.MyBatis-Plus


mybatis.plus/guide

MyBatis-Plus是原生MyBatis的一个增强工具,可以在使用原生MyBatis的所有功能的基础上,使用plus特有的功能。


MyBatis-Plus的核心功能:


通用 CRUD:定义好Mapper接口后,只需要继承BaseMapper 接口即可获得通用的增删改查功能,无需编写任何接口方法与配置文件。


条件构造器:通过EntityWrapper(实体包装类),可以用于拼接 SQL 语句,并且支持排序、分组查询等复杂的SQL。


代码生成器:支持一系列的策略配置与全局配置,比MyBatis的代码生成更好用。

另外MyBatis-Plus也有分页的功能。



相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
Java 数据库连接 Spring
“探索Spring与MyBatis集成的最佳实践与技巧“(上)
“探索Spring与MyBatis集成的最佳实践与技巧“
290 0
|
8月前
|
SQL Java 数据库连接
MyBatis插件深度解析:功能、原理、使用、应用场景与最佳实践
MyBatis插件深度解析:功能、原理、使用、应用场景与最佳实践
|
Java 数据库连接 mybatis
“探索Spring与MyBatis集成的最佳实践与技巧“(下)
“探索Spring与MyBatis集成的最佳实践与技巧“
65 0
|
XML Java 数据库连接
深入浅出:MyBatis的使用方法及最佳实践
深入浅出:MyBatis的使用方法及最佳实践
MyBatis这样用,同事直呼哇塞,堪称最佳实践
MyBatis是一款非常流行的ORM框架,相信很多小伙伴都在使用。我们经常会把它和MyBatis-Plus或者MBG一起使用,用多了之后对于其一些常规操作就不太熟悉了。最近总结了下MyBatis的实用用法和技巧,希望对大家有所帮助!
|
SQL 缓存 Java
MyBatis-最佳实践
MyBatis-最佳实践
MyBatis-最佳实践
|
SQL Java 数据库连接
MyBatis根据表结构自动生成PO/Mapper代码的最佳实践
MyBatis根据表结构自动生成PO/Mapper代码的最佳实践
1302 0
MyBatis根据表结构自动生成PO/Mapper代码的最佳实践
|
Java 数据库连接 数据库
MyBatis-Generator最佳实践
引用地址:http://arccode.net/2015/02/07/MyBatis-Generator%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/ 最近使用MyBatis开发项目,为了快速开发,发现了一个可快速生成mapper类和mapper配置文件及Model的插件-MyBatis-Generator,总结下该插件的使用及最佳实践.
1388 0
|
19天前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
34 2
|
4月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
196 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。