MyBatis 汇总

简介: 本文介绍了MyBatis的核心配置与使用技巧,涵盖属性加载优先级、多环境配置、事务管理、XML映射(一对一、一对多、多对多)、分页实现方式(逻辑与物理分页)及缓存机制,并简要分析了执行器类型与批量操作原理,助力高效开发。

1.前言

mybatis官网Java-api地址:https://mybatis.org/mybatis-3/zh/java-api.html

2.常见配置

如果一个属性不止在一个地方进行配置,那么mybatis将按照下面顺序进行加载

  • 首先读取properties元素体内的属性
  • 然后根据properties元素中的resource属性读取类路径下属性文件,或根据url属性指定的路径读取属性文件,并覆盖之前读取过的同名属性
  • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性

因此,优先级顺序:方法参数传递的属性>resource/url属性中配置>properties元素中指定属性

2.1 几个常见配置属性

设置名

描述

有效值

默认值

cacheEnabled

全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。

true | false

true

lazyLoadingEnabled

延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。

true | false

false

useGeneratedKeys

允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。

true | false

False

defaultExecutorType

配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。

SIMPLE REUSE

BATCH

SIMPLE

localCacheScope

MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。

SESSION STATEMENT

SESSION

proxyFactory

指定 Mybatis 创建可延迟加载对象所用到的代理工具。

CGLIB | JAVASSIST

JAVASSIST (3.3 以上)

2.2 多环境配置


多个数据源,就创建多个SqlSessionFactory,每个对应一个数据库


为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);



如果忽略了环境参数,那么将会加载默认环境,如下所示:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);



environments 元素定义了如何配置环境:

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

几个关键点:

  • 默认使用的环境 ID(比如:default="development")。
  • 每个 environment 元素定义的环境 ID(比如:id="development")。
  • 事务管理器的配置(比如:type="JDBC")。
  • 数据源的配置(比如:type="POOLED")。

默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

2.3 事务管理

2.3.1 JDBC

这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域

2.3.2 MANAGED

它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。

注意:

如果用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。这两种事务管理器类型都不需要设置任何属性。


3.XML(mapper)

3.1 一对一

定义一个一对一的Result,进行属性-字段之间的一对一关联映射即可,如果属性和字段是一致的,resultType实际也是可以的,resultMap更多是解决字段-属性不一致(满足驼峰命名就是一致),如id(属性)-USER_ID(字段)

3.2 一对多

设:一个用户对应多个角色

  • User类中添加List<Role>
  • 一的mapper.xml中,resultMap添加<collection>标签.

如:

<resultMap id="userMap" type="User">
  <id property="id" column="id"></id>
  <result property="username" column="username"></result>
  <result property="password" column="password"></result>
  <result property="address" column="address"></result>
  <result property="email" column="email"></result>
  
  <collection property="roles" ofType="Role">
    <id property="id" column="role_id"></id>
    <result property="name" column="role_name"></result>
  </collection>
</resultMap>

会得到类似这样的数据

{
    "id": "1003",
    "username": "小波",
    "password": "123456",
    "address": "北京市东城区",
    "email": "510273027@qq.com",
    "roles": [
        {
            "id": "1",
            "name": "开发"
        },
        {
            "id": "2",
            "name": "TL"
        }
    ]
}

3.3 多对一

设:一个作者可以有多个博客

  • Author类中添加Blog
  • 一的mapper.xml中添加<association>

如:

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap>
<resultMap id="authorResult" type="Author">
  <id property="id" column="author_id"/>
  <result property="username" column="author_username"/>
</resultMap>

或:

<resultMap id="productBean" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <!-- 多对一 -->
  <!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
  <association property="category" javaType="Author">
    <id column="cid" property="author_id"/>
    <result column="username" property="username"/>
  </association>
</resultMap>

3.4 多对多

设:多个部门对应多个用户

  • 定义一个第三方类,假设为UserForDept.java,属性private User user; private Dept dept;
  • User类中添加Set<Dept>(针对不同场合这里也可以List),mapper.xml中添加<collection>添加UsersForDept
  • Dept类中添加Set<User>(针对不同场合这里也可以List),mapper.xml中添加<collection>添加UsersForDept

4.分页

4.1 自带rowbound分页

先将所有的结果集查询出来ResultSet,再进行内存分页(limit)

4.2 第三方插件pagehelper

会将一个查询SQL变成两部分执行,假设SQL是:select name from user;

①自动识别数据库类型,添加对应的分页关键字,如MySQL则limit,Oracle则rownum,DB2则fetch,查找出上面SQL的结果

②查找出上面结果,查询结果的总条数count

4.3 SQL分页

依赖limit进行实现,或者rownum等自身的SQL实现

4.4 数组分页


简而言之:查全部再subList


首先在dao层,创建StudentMapper接口,用于对数据库的操作。在接口中定义通过数组分页的查询方法,如下所示:

List<Student> queryStudentsByArray();


方法很简单,就是获取所有的数据,通过list接收后进行分页操作。创建StudentMapper.xml文件,编写查询的sql语句:

<select id="queryStudentsByArray"  resultMap="studentmapper"> select * from student </select>


可以看出再编写sql语句的时候,我们并没有作任何分页的相关操作。这里是查询到所有的学生信息。接下来在service层获取数据并且进行分页实现:

定义IStuService接口,并且定义分页方法:

List<Student> queryStudentsByArray(int currPage, int pageSize);


通过接收currPage参数表示显示第几页的数据,pageSize表示每页显示的数据条数。

创建IStuService接口实现类StuServiceIml对方法实现,对获取到的数组通过currPage和pageSize进行分页:

@Override    
public List<Student> queryStudentsByArray(int currPage, int pageSize) { 
    List<Student> students = studentMapper.queryStudentsByArray(); 
    //  从第几条数据开始        
    int firstIndex = (currPage - 1) * pageSize; 
    //  到第几条数据结束        
  int lastIndex = currPage * pageSize; return students.subList(firstIndex, lastIndex); 
}



通过subList方法,获取到两个索引间的所有数据。

最后在controller中创建测试方法:

@ResponseBody      
@RequestMapping("/student/array/{currPage}/{pageSize}") 
public List<Student> getStudentByArray(@PathVariable("currPage") int currPage, @PathVariable("pageSize") int pageSize) { 
  List<Student> student = StuServiceIml.queryStudentsByArray(currPage, pageSize); 
    return student; 
}



通过用户传入的currPage和pageSize获取指定数据。

4.5 拦截器分页

自定义拦截器实现了拦截所有以ByPage【或自己约束的都是可以的】结尾的查询语句,并且利用获取到的分页相关参数统一在sql语句后面加上limit分页的相关语句。

4.6 总结

逻辑分页:即内存分页,就是mybatis自带的rowbounds,内存开销大,数据量小效率比物理分页快,但大数据量,易内存溢出

物理分页:上述2345,小数据量效率比逻辑分页慢,但是大数据量推荐用物理分页。

物理分页总是优先于逻辑分页。

5.缓存

5.1 一级缓存

5.2 二级缓存

6.执行器

6.1 SimpleExecutor

每执行一次update/select,就开启一个Statement对象,用完立刻关闭Statement对象

6.2 ReuseExecutor

执行update/select,以SQL为key查找Statement对象,存在就使用,不存在则创建,用完后不关闭Satementer而是放置在Map中,以便下次使用。简而言之就是重复使用Statement对象。

6.3 BatchExecutor

执行update(没有select,JDBC批处理不支持select),将所有的SQL添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()后等待注意执行executeBatch()批处理,与JDBC批处理一样。



7.insert/update实现源码

8.批量操作源码

9.优化

相关文章
|
2月前
|
Java 数据库连接 mybatis
MyBatis映射关系(1-1 1-n n-n)
本文介绍了MyBatis中四种核心映射关系:一对一、一对多、多对一、多对多。通过resultMap实现属性与字段的映射,解决命名不一致问题;一对多使用`&lt;collection&gt;`,多对一使用`&lt;association&gt;`,多对多则借助中间类关联双方集合,实现复杂数据结构的封装与查询。
|
2月前
|
存储 NoSQL 关系型数据库
4-MongoDB索引知识
MongoDB索引基于B树结构,可高效支持查询,避免全集合扫描。主要类型包括单字段索引、复合索引、地理空间索引、文本索引和哈希索引,适用于不同查询场景,显著提升查询性能。
 4-MongoDB索引知识
|
2月前
|
Java 关系型数据库 开发工具
自救手册
本文档为新员工入职指南,涵盖首日工作流程:账号开通、开发环境配置(JDK、Maven、IDEA)、代码拉取与Git操作、常用中间件访问及故障排查。包含Nacos、MySQL、Redis等连接配置,Git常用命令与冲突解决,并介绍如何构建二方包和搭建Spring Boot工程,助力快速上手项目开发。
 自救手册
|
2月前
|
Java Maven
3. 打包
本文介绍Java项目打包为可执行JAR文件的两种方式:一是将所有内容打包进单一JAR,通过Maven配置spring-boot-maven-plugin实现;二是将JAR、依赖与配置文件分离。涵盖配置方法、打包命令(mvn clean package)、运行与停止指令(java -jar、kill -9 pid)等操作步骤。
 3. 打包
|
2月前
|
存储 安全 Java
6.鉴权
本文介绍基于Spring Security与JWT的客户端Token认证方案,涵盖实现思路、核心代码及完整流程。通过自定义过滤器与认证逻辑,结合RBAC权限模型,实现安全的Token生成、校验与访问控制,保护Spring Boot应用接口。
 6.鉴权
|
2月前
|
存储 缓存 Java
自动装配机制
本文深入解析SpringBoot自动装配机制,围绕@SpringBootApplication注解展开,剖析其组合注解中的@ComponentScan、@SpringBootConfiguration与@EnableAutoConfiguration核心原理,详解元注解作用及自动配置类如何通过spring.factories实现自动化加载与组件过滤。
 自动装配机制
|
2月前
|
安全 Java 数据安全/隐私保护
2.通用权限管理模型
本文介绍了ACL和RBAC两种常见的权限模型。ACL通过直接为用户或角色授权实现访问控制,简单直观;RBAC则基于角色分配权限,解耦用户与权限关系,更易维护。文中还详解RBAC0-3的演进,涵盖角色继承、职责分离等核心概念,帮助构建系统化权限认知。
 2.通用权限管理模型
|
2月前
|
安全 Java Spring
2.过滤器链加载原理
本文深入解析Spring Security底层过滤机制,揭示十五个过滤器如何通过DelegatingFilterProxy和FilterChainProxy自动加载并执行,最终明确SecurityFilterChain才是真正的过滤器链实现。
|
2月前
|
缓存 Java 数据库连接
MyBatis常见配置
本文介绍MyBatis核心配置,包括属性加载优先级(方法参数 &gt; resource/url &gt; properties元素)、常用配置项如缓存、延迟加载、执行器类型,以及多环境配置与事务管理(JDBC/MAINTAINED),适用于多数据源场景。
|
2月前
|
SQL Java 关系型数据库
MyBatis分页
本文介绍六种分页实现方式:MyBatis自带RowBounds内存分页、PageHelper插件分页、SQL原生分页、数组分页、拦截器分页,并对比逻辑分页与物理分页的优劣。大数据量下推荐物理分页,避免内存溢出,提升性能。

热门文章

最新文章