当前位置: 首页 > news >正文

MyBatis 核心概念与实践指南:从代理模式到性能优化

 1. 什么是 MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。

起源与发展:MyBatis 的前身是 Apache 的 iBatis 项目,2010年迁移至 Google Code 并更名为 MyBatis,2013年正式迁移至 Github。

核心思想:通过 XML 或注解来配置和映射原始类型、接口和 Java POJO (Plain Old Java Objects) 为数据库中的记录。

ORM 程度:MyBatis 属于半自动化 ORM 框架。

- O (Object):Java 实体类对象

- R (Relation):关系型数据库中的表

- M (Mapping):建立实体类属性与表字段之间的映射关系

为什么需要半自动化?

- 灵活性:对于复杂的多表关联查询、分页查询、复杂条件查询等,全自动 ORM(如 Hibernate)生成的 SQL 可能不够优化或非常复杂

- 性能:直接编写 SQL 可以更好地利用数据库的特性(如存储过程、特定函数的调用),有利于性能调优

 2. 【代理模式】下开发 Mapper 层的规则

MyBatis 的代理模式使得开发者只需定义接口,MyBatis 会动态生成其实现类,极大简化了开发。

需要遵守的规则:

1. 接口与 XML 文件同名且在同一个包下

   - `UserMapper.java` 接口与 `UserMapper.xml` 文件必须同名

   - 位于相同的包目录结构中(Maven 项目通常将 xml 文件放在 resources 的对应目录下)

2. XML 中的 namespace 配置

   - XML 文件中的 namespace 属性必须是接口的全限定名

   - 示例:`namespace="com.example.dao.UserMapper"`

3. 方法名与 SQL ID 一致

   - 接口中的方法名必须与 XML 文件中 SQL 语句的 id 属性值一致

4. 输入参数类型一致

   - 接口方法的输入参数类型必须与 XML 中 SQL 语句的 parameterType 指定类型一致

   - 使用 @Param 注解或多参数时可不指定 parameterType

5. 返回值类型一致

   - 接口方法的返回值类型必须与 XML 中 SQL 语句的 resultType(或 resultMap)指定类型一致

   - 返回集合时,resultType 指定的是集合中元素的类型

使用代理模式的好处:

- 代码更简洁:无需编写接口的实现类

- 类型安全:编译时就能发现错误

- 解耦:SQL 与 Java 代码完全分离,职责清晰

代理模式原理:MyBatis 通过 JDK 动态代理技术,在运行时为 Mapper 接口创建代理对象。当调用接口方法时,代理对象会拦截方法调用,根据方法名找到对应的 SQL 语句并执行。

 3. 常用的【动态 SQL】标签

MyBatis 提供了丰富的动态 SQL 标签来处理复杂的查询条件:

1. if:条件判断,用于动态包含 WHERE 或 SET 子句的一部分

2. choose、when、otherwise:类似于 Java 中的 switch-case-default 语句

3. trim:自定义字符串的修剪(前缀、后缀)

4. where:智能生成 WHERE 子句,自动去除开头的 AND 或 OR

5. set:智能生成 SET 子句,用于更新语句

6. foreach:遍历集合,常用于 IN 条件或批量操作

7. bind:创建变量并绑定到上下文

8. sql:定义可重用的 SQL 代码片段

9. include:引用通过 sql 定义的代码片段

10. script:在注解中使用动态 SQL

foreach 标签详解:

```xml

<select id="selectUsersByIds" resultType="User">

    SELECT  FROM user

    WHERE id IN

    <foreach collection="ids" item="id" open="(" separator="," close=")">

        {id}

    </foreach>

</select>

```

对应 Java 接口:

```java

List<User> selectUsersByIds(@Param("ids") List<Integer> idList);

```

foreach 属性:

- `collection`:要遍历的集合属性名

- `item`:每次遍历时生成的变量名

- `index`:遍历 List 或数组时的索引

- `open`:循环内容开始时的字符串

- `close`:循环内容结束时的字符串

- `separator`:每次循环之间的分隔符

动态 SQL 的好处:

- 灵活性:根据运行时条件动态构建 SQL

- 可维护性:条件判断逻辑写在 XML 中,与 Java 代码分离

- 减少代码冗余:避免字符串拼接组装 SQL

 4. 【关联查询】:多表查询

MyBatis 处理多表关联查询主要有两种方式:

 方式一:使用 ResultMap 进行关联映射

1. 编写多表联查的 SQL

2. 修改 POJO:在"一"的一方添加"多"的集合属性,在"多"的一方添加"一"的对象属性

3. 配置 ResultMap:使用 association 和 collection 标签

```xml

<resultMap id="userWithOrdersMap" type="User">

    <id property="id" column="user_id"/>

    <result property="name" column="user_name"/>

    <collection property="orders" ofType="Order">

        <id property="id" column="order_id"/>

        <result property="orderNumber" column="order_number"/>

    </collection>

</resultMap>

<select id="selectUserWithOrders" resultMap="userWithOrdersMap">

    SELECT

        u.id AS user_id, u.name AS user_name,

        o.id AS order_id, o.order_number

    FROM user u

    LEFT JOIN orders o ON u.id = o.user_id

    WHERE u.id = {userId}

</select>

```

 方式二:使用 ResultType 映射到 VO/DTO

1. 编写多表联查的 SQL

2. 创建 VO/DTO:包含所有需要查询返回的字段

3. 配置 ResultType:直接映射到自定义的 VO 类

```java

public class UserOrderVO {

    private Integer userId;

    private String userName;

    private Integer orderId;

    private String orderNumber;

    // getters & setters

}

```

```xml

<select id="selectUserOrderVO" resultType="com.example.vo.UserOrderVO">

    SELECT

        u.id AS userId, u.name AS userName,

        o.id AS orderId, o.order_number AS orderNumber

    FROM user u

    LEFT JOIN orders o ON u.id = o.user_id

    WHERE u.id = {userId}

</select>

```

对比:

- ResultMap:更面向对象,适合关系复杂的领域模型映射

- VO/ResultType:更轻量灵活,适合定制化的查询结果

 5. 延迟加载(懒加载)

概念:在关联查询时,先加载主对象,只有在程序真正需要使用关联对象时,才发起第二次 SQL 查询加载关联数据。

好处:

- 性能提升:减少不必要的数据库查询

- 降低数据库压力:加快初始查询速度

坏处:

- "N+1 查询问题":可能导致性能下降

- 调试困难:异常可能不会立即抛出

应用场景:适用于可能不需要立即加载的大对象

 6. 查询缓存

MyBatis 提供了查询缓存来提高查询速度,减少数据库压力。

其他常见的数据库优化手段:

1. 数据库连接池 (如 HikariCP, Druid)

2. 使用索引:为查询条件字段建立合适的索引

3. 优化 SQL:避免 SELECT ,使用 LIMIT 分页

4. 应用层缓存:MyBatis 的查询缓存

 MyBatis 缓存分为两级:

一级缓存:

- 范围:SqlSession 级别

- 状态:默认开启,无法关闭

- 失效时机:执行增删改操作、调用 clearCache() 或关闭 SqlSession

二级缓存:

- 范围:Mapper (Namespace) 级别

- 状态:默认关闭,需要手动配置开启

- 工作机制:SqlSession 关闭或提交后,一级缓存内容转存到二级缓存

开启二级缓存的步骤:

1. 核心配置文件开启全局开关:

   ```xml

   <settings>

       <setting name="cacheEnabled" value="true"/>

   </settings>

   ```

2. 在具体的 Mapper.xml 中配置:

   ```xml

   <cache/>

   ```

3. POJO 实现 Serializable 接口

使用第三方缓存(如 Ehcache):

1. 添加依赖:mybatis-ehcache

2. 配置使用 Ehcache:

   ```xml

   <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

   ```

3. 配置 ehcache.xml(可选)

缓存选择建议:

- 读多写少且数据实时性要求不高的场景:使用二级缓存

- 读写频繁或数据实时性要求高的场景:关闭二级缓存

 总结

MyBatis 作为一个半自动化的 ORM 框架,在灵活性和性能之间找到了良好的平衡点。通过掌握代理模式下的开发规则、动态 SQL 的使用、关联查询的处理方式以及缓存机制,可以充分发挥 MyBatis 的优势,构建高效、可维护的数据访问层。

在实际项目中,应根据具体业务需求选择合适的查询方式和缓存策略,在保证数据一致性的前提下提升系统性能。


文章转载自:

http://psyusHgd.wfjrL.cn
http://3NhVjATE.wfjrL.cn
http://UARyeBkO.wfjrL.cn
http://M6jSjjup.wfjrL.cn
http://xfKkGXh2.wfjrL.cn
http://k4WbXZwv.wfjrL.cn
http://mLot7pny.wfjrL.cn
http://5eRimo2Y.wfjrL.cn
http://hYOWMFG4.wfjrL.cn
http://e1y8aN18.wfjrL.cn
http://RusSouU0.wfjrL.cn
http://V7AG8aeU.wfjrL.cn
http://qaY9wvtu.wfjrL.cn
http://mvMXIun0.wfjrL.cn
http://xJYLyobj.wfjrL.cn
http://36TTXM96.wfjrL.cn
http://NxQwYLS7.wfjrL.cn
http://9CdtEbbl.wfjrL.cn
http://MbwCLlVs.wfjrL.cn
http://g5Y61TDw.wfjrL.cn
http://BRqt08mX.wfjrL.cn
http://pNu9ooA2.wfjrL.cn
http://SssuYCTh.wfjrL.cn
http://FiRkRDmX.wfjrL.cn
http://1cat7ypm.wfjrL.cn
http://qAaaHUVO.wfjrL.cn
http://m5Ov5ksR.wfjrL.cn
http://JUJSp7Mh.wfjrL.cn
http://7eBer2GF.wfjrL.cn
http://WIbWT6go.wfjrL.cn
http://www.dtcms.com/a/384258.html

相关文章:

  • 全链路性能优化实战:从Jmeter压测到系统调优
  • 《华为变革法:打造可持续进步的组织》读书笔记
  • VS Code 通用配置分享(Cursor / QCode / Trae 通用)
  • python 自动化从入门到实战-word转为 PDF 文件(4)
  • Python爬虫实战:研究Pandas,构建地理信息数据采集和分析系统
  • 【Linux】进程概念(二):进程查看与 fork 初探
  • Python 自动化从入门到实战-一键将 Excel 表格转为 PDF 文件(3)
  • FFMPEG FLV
  • Spring Cloud Alibaba 与 Spring Boot、Spring Cloud 的版本兼容性对照
  • 猫头虎AI分享Excel MCP技术解析让AI智能操作Excel表格的完整指南
  • Keka 解压/压缩工具(Mac电脑)
  • 【Linux网络】网络基础概念——带你打开网络的大门
  • 2023年CSP-X初赛真题及答案解析(20)
  • C++---存储周期,作用域,链接性
  • 从零到一:用 Qt + libmodbus 做一个**靠谱**的 Modbus RTU 小工具(实战总结)
  • 如何查看iOS设备电量与电池使用情况 iPhone电池寿命查询、App耗电监控、续航优化与性能调试(uni-app iOS开发指南)
  • Android 14 servicemanager的前世今生2
  • Android RecyclerView展示List<View> Adapter的数据源使用View
  • 深圳比斯特|电池组PACK自动化生产线厂家概述
  • 查看iOS App 性能监控全流程 如何监控CPU内存GPU帧率、电池能耗与网络延迟(uni-app iOS开发与调试优化指南)
  • AI渗透测试工具“Villager“整合Kali Linux工具与DeepSeek AI实现自动化攻击
  • uniAPP安装 uni-popup,弹窗提示
  • 无人机图传系统的功能解析和技术实现原理
  • Linux笔记---HTTPS的原理
  • 如何抓包?iOS 抓包方法、HTTPS 抓包工具选择与手机网络调试全攻略
  • 第22课:DevOps与CI、CD
  • JDK 8调用HTTPS POST接口的SSL配置
  • HTTPS 的加密
  • 基于 EPGF 架构理念的 FaceFusion 3.4.1 本地 .venv 部署教程(非 Conda 环境部署优化版)
  • RabbitMQ 高级功能与优化篇