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

Java——MyBatis 核心特性全解析:从配置到高级用法

MyBatis 核心特性全解析:从配置到高级用法

MyBatis 作为一款灵活高效的持久层框架,其核心特性涵盖配置管理、参数处理、查询优化等多个方面。本文基于官方文档,从核心配置、参数处理、高级查询到缓存策略,全面解析 MyBatis 的核心用法,帮助开发者深入理解并灵活运用框架特性。

一、核心配置文件详解

MyBatis 的核心配置文件(如 SqlMapConfig.xml)是框架运行的基础,包含了数据源、别名、环境等关键配置,以下是核心标签的详细说明:

1. <properties>:属性配置

用于引入外部配置文件或定义内部属性,实现动态配置数据源信息,提高配置灵活性。

  • 引入外部文件:

    <properties resource="db.properties"/> <!-- 引用resources目录下的db.properties -->
    

    外部文件 db.properties 内容:

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    jdbc.username=root
    jdbc.password=root
    
  • 内部定义属性:

    <properties><property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
    </properties>
    
  • 使用属性:通过 ${属性名} 引用,例如配置数据源时:

    <dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/>
    </dataSource>
    

2. <typeAliases>:类型别名

为 Java 类定义简短别名,简化映射文件中类型的引用,减少冗余代码。

  • 单个类别名:

    <typeAliases><typeAlias type="com.example.pojo.User" alias="User"/> <!-- 为User类定义别名"User" -->
    </typeAliases>
    

    映射文件中可直接使用别名:

    <select id="findAll" resultType="User">select * from user</select>
    
  • 包扫描别名:为指定包下所有类自动生成别名(别名与类名相同,首字母可小写):

    <typeAliases><package name="com.example.pojo"/> <!-- 包下所有类自动生成别名 -->
    </typeAliases>
    
  • 系统默认别名:MyBatis 对常用类型提供默认别名,如 string 对应 java.lang.Stringint 对应 java.lang.Integer 等。

3. <environments>:环境配置

用于配置数据库环境(如开发、测试、生产环境),支持多环境切换,通过 default 指定默认环境。

  • 事务管理器:<transactionManager> 配置事务管理方式,type="JDBC" 表示使用 JDBC 自带的事务管理(手动提交/回滚);
  • 数据源:<dataSource> 配置数据库连接,type="POOLED" 表示使用 MyBatis 自带的连接池(推荐),UNPOOLED 表示不使用连接池,JNDI 表示由容器管理连接。

示例配置:

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

4. <mappers>:映射器配置

用于注册映射文件或 Mapper 接口,只有注册后才能被 MyBatis 识别。支持四种注册方式:

  • 相对路径注册映射文件:
    <mappers><mapper resource="com/example/mapper/UserMapper.xml"/>
    </mappers>
    
  • 绝对路径注册映射文件:
    <mapper url="file:///D:/project/mapper/UserMapper.xml"/>
    
  • 注册 Mapper 接口(适合注解开发):
    <mapper class="com.example.mapper.UserMapper"/>
    
  • 包扫描注册(注册指定包下所有接口):
    <package name="com.example.mapper"/>
    

二、映射文件高级特性

映射文件(如 UserMapper.xml)是 MyBatis 定义 SQL 语句和映射规则的核心,除了基础的 CRUD 标签,还有多个高级标签用于优化 SQL 编写。

1. <resultMap>:自定义映射关系

当 POJO 属性名与数据库列名不一致时,通过 <resultMap> 手动建立映射关系,解决自动映射失效问题。
示例:数据库表 teacher 列名为 tidtname,POJO 类 Teacher 属性为 idteacherName

<resultMap id="teacherMap" type="Teacher"><id property="id" column="tid"/> <!-- 主键映射:POJO属性id对应列tid --><result property="teacherName" column="tname"/> <!-- 普通字段映射:teacherName对应tname -->
</resultMap><select id="findAll" resultMap="teacherMap">select * from teacher <!-- 使用自定义映射 -->
</select>

2. <sql><include>:SQL 片段复用

将重复的 SQL 片段(如查询字段、条件)定义在 <sql> 中,通过 <include> 引用,减少代码冗余。
示例:复用查询字段片段:

<sql id="userColumns">id, username, sex, address</sql> <!-- 定义可复用的字段片段 --><select id="findById" resultType="User">select <include refid="userColumns"/> from user where id = #{id} <!-- 引用片段 -->
</select><select id="findAll" resultType="User">select <include refid="userColumns"/> from user <!-- 多次复用 -->
</select>

3. 特殊字符处理

映射文件中直接使用 <>& 等特殊字符会导致 XML 解析错误,需使用实体符号替代:

符号实体符号
<&lt;
>&gt;
&&amp;
'&apos;
"&quot;

示例:查询年龄大于 18 的用户:

<select id="findAdult" resultType="User">select * from user where age &gt; 18 <!-- 使用&gt;替代> -->
</select>

三、参数处理机制

MyBatis 提供了灵活的参数处理方式,支持单参数、多参数传递,以及动态参数拼接,满足不同场景的需求。

1. #{} ${} 的区别

两者均用于接收参数,但使用场景和安全性不同:

  • #{} :SQL 占位符,参数会被预编译为 ?,自动添加引号,可防止 SQL 注入,推荐优先使用
    示例:

    <select id="findByName" parameterType="string" resultType="User">select * from user where username like #{name} <!-- 参数自动加引号,如'%张三%' -->
    </select>
    
  • ${} :字符串拼接,参数直接嵌入 SQL 语句,无法防止 SQL 注入,适用于动态表名、排序字段等场景。
    示例:动态指定排序字段:

    <select id="findOrder" parameterType="string" resultType="User">select * from user order by ${sortField} <!-- 直接拼接字段名,如"age desc" -->
    </select>
    

    注意:使用 ${} 时,若参数为单一值,参数名必须为 value(如 ${value})。

2. 多参数传递方式

当 Mapper 接口方法包含多个参数时,MyBatis 提供四种传递方式:

(1)顺序传参

通过 arg0、arg1...param1、param2... 引用参数,按参数顺序匹配(可读性差,不推荐)。
示例:

// 接口方法
List<User> findPage(int startIndex, int pageSize);

映射文件:

<select id="findPage" resultType="User">select * from user limit #{arg0}, #{arg1} <!-- arg0对应第一个参数,arg1对应第二个参数 -->
</select>
(2)@Param 注解传参

在参数前通过 @Param 定义名称,映射文件中直接使用该名称引用(推荐,参数直观)。
示例:

// 接口方法
List<User> findPage1(@Param("startIndex") int startIndex, @Param("pageSize") int pageSize);

映射文件:

<select id="findPage1" resultType="User">select * from user limit #{startIndex}, #{pageSize} <!-- 直接使用注解定义的名称 -->
</select>
(3)POJO 传参

将参数封装到 POJO 类中,映射文件通过 POJO 的属性名引用(适合参数较多的场景)。
示例:

// 自定义POJO
public class PageQuery {private int startIndex;private int pageSize;// getter/setter
}// 接口方法
List<User> findPage2(PageQuery pageQuery);

映射文件:

<select id="findPage2" parameterType="PageQuery" resultType="User">select * from user limit #{startIndex}, #{pageSize} <!-- 引用POJO的属性 -->
</select>
(4)Map 传参

使用 Map 存储参数,映射文件通过 Map 的 Key 引用(无需自定义 POJO,灵活度高)。
示例:

// 接口方法
List<User> findPage3(Map<String, Object> params);

映射文件:

<select id="findPage3" parameterType="map" resultType="User">select * from user limit #{startIndex}, #{pageSize} <!-- 引用Map的Key -->
</select>

测试时传入参数:

Map<String, Object> params = new HashMap<>();
params.put("startIndex", 0);
params.put("pageSize", 3);
userMapper.findPage3(params);

四、主键回填与高级查询

1. 主键回填

当插入数据时需要获取自增主键(如 MySQL 的自增 ID),可通过 <selectKey> 标签实现主键回填。
示例:

<insert id="add" parameterType="User"><!-- 主键回填配置 --><selectKey keyProperty="id" <!-- POJO中主键属性名 -->keyColumn="id" <!-- 数据库中主键列名 -->resultType="int" <!-- 主键类型 -->order="AFTER" <!-- 在insert后执行(自增主键需用AFTER) -->>SELECT LAST_INSERT_ID() <!-- 查询刚插入的主键值(MySQL专用) --></selectKey>insert into user(username, sex, address) values(#{username}, #{sex}, #{address})
</insert>

测试时,插入后可直接获取主键:

User user = new User("张三", "男", "北京");
userMapper.add(user);
session.commit();
System.out.println("新增用户ID:" + user.getId()); // 输出自增ID

2. Example 类高级查询(MyBatis Generator)

MyBatis Generator(MBG)可自动生成 Example 类,用于构建复杂查询条件(如多条件组合、排序、分页等),无需手动编写动态 SQL。

(1)Example 类核心组件
  • Criteria:生成查询条件的工具类,通过 andXXX() 方法添加条件;
  • or():将多个条件组合为 OR 关系(默认为 AND);
  • setOrderByClause():设置排序规则。
(2)使用示例

假设有 Product 表,MBG 生成 ProductExample 类,实现多条件查询:

  • 多条件 AND 查询:

    ProductExample example = new ProductExample();
    ProductExample.Criteria criteria = example.createCriteria();
    criteria.andProductNameLike("%课程%"); // 商品名包含"课程"
    criteria.andPriceBetween(0.0, 20000.0); // 价格在0到20000之间
    List<Product> products = productMapper.selectByExample(example);
    
  • 多条件 OR 查询:

    ProductExample example = new ProductExample();
    // 条件1:价格<100
    ProductExample.Criteria c1 = example.createCriteria();
    c1.andPriceLessThan(100.0);// 条件2:商品名包含"免费"
    ProductExample.Criteria c2 = example.createCriteria();
    c2.andProductNameLike("%免费%");example.or(c2); // 组合为OR关系
    List<Product> products = productMapper.selectByExample(example);
    
  • 排序查询:

    ProductExample example = new ProductExample();
    example.setOrderByClause("price desc"); // 按价格降序
    List<Product> products = productMapper.selectByExample(example);
    

五、缓存与加载策略

1. 缓存机制

MyBatis 提供两级缓存,减少数据库交互,提高查询效率:

  • 一级缓存:存在于 SqlSession 中,默认开启,同一 SqlSession 内的相同查询复用缓存。
    失效场景:执行增删改操作、调用 clearCache()/commit()、关闭 SqlSession

  • 二级缓存:存在于 SqlSessionFactory 中,需手动开启,同一工厂创建的 SqlSession 共享缓存。
    开启步骤:

    1. 核心配置文件开启缓存开关(默认开启):
      <settings><setting name="cacheEnabled" value="true"/>
      </settings>
      
    2. 映射文件中声明缓存:
      <mapper namespace="com.example.mapper.UserMapper"><cache size="2048"/> <!-- 开启二级缓存,最多缓存2048个对象 -->
      </mapper>
      
    3. POJO 类实现 Serializable 接口(二级缓存存储对象数据,需序列化)。

2. 延迟加载(懒加载)

分解式查询(N+1 查询)中,延迟加载可实现“按需查询”,仅在使用关联数据时才执行查询,减少不必要的数据库交互。

  • 开启全局延迟加载:

    <settings><setting name="lazyLoadingEnabled" value="true"/> <!-- 全局开启延迟加载 -->
    </settings>
    
  • 局部设置加载方式:在关联查询中通过 fetchType 指定(lazy 延迟加载,eager 立即加载):

    <!-- 一对多查询:班级->学生,延迟加载学生列表 -->
    <collection property="studentList" column="cid" ofType="Student" select="com.example.mapper.StudentMapper.findByClassId"fetchType="lazy"
    />
    
  • 防止 toString() 触发延迟加载:默认情况下,调用 toString() 会触发延迟加载,可通过配置禁用:

    <settings><setting name="lazyLoadTriggerMethods" value=""/> <!-- 清空触发方法 -->
    </settings>
    

总结

MyBatis 的核心特性围绕“灵活”与“高效”设计,从配置文件的动态管理到参数处理的多样方式,从高级查询的 Example 类到缓存与加载策略的优化,每一项特性都旨在简化开发并提升性能。掌握这些核心特性,能帮助开发者在实际项目中灵活应对复杂业务场景,写出高效、易维护的持久层代码。

http://www.dtcms.com/a/291478.html

相关文章:

  • Python桌面版数独游戏(三版)-增加难易度模式
  • 深入解析:GRPO决策优化与动态规划在先进RAG系统中的应用
  • Markdown语法完全指南:从入门到精通
  • MySQL 8.0 OCP 1Z0-908 题目解析(32)
  • spring boot windows linux 控制台 文件 乱码问题详解
  • Spring的IOC是什么?它解决了哪些问题?
  • JVM对象创建与内存分配机制
  • 上海RISC-V峰会-香山开源RISC-V CPU随想随记
  • Golang在Web开发中的应用
  • 设备虚拟化
  • hard_err错误
  • 50-字母异位词分组
  • SmartETL循环流程的设计与应用
  • 外辐射源入门综述
  • 板凳-------Mysql cookbook学习 (十二--------4)
  • c++找工作(qt)
  • 【金仓数据库产品体验官】_KingbaseES(SQLServer兼容版)保姆级安装教程
  • LiteCoT:难度感知的推理链压缩与高效蒸馏框架
  • 【CNN】卷积神经网络多通道卷积与偏置过程- part2
  • AI Red Teaming 分析
  • 鸿蒙开发中与 AI 编码助手的共处之道(ArkTS 视角)
  • sky-take-out项目中Redis的使用
  • 【每日算法】专题十七_多源 BFS
  • Java 实现 UDP 多发多收通信
  • 图论(2):最短路
  • http协议学习-body各种类型
  • cs336 Lecture2
  • SQL基础入门② | 运算符篇
  • 【HarmonyOS】ArkTS语法详细解析
  • 阿里云技术三面:java社招面经+面试题分享!