Mybatis优化检索的方法详解
作者:兔子队列
MyBatis是一款优秀的基于Java的持久层框架,它可以将 SQL 语句和数据库中的记录映射成为 Java 对象,并且支持灵活的 SQL 查询语句,在Mybatis中,可以使用动态SQL来灵活构造SQL语句,从而满足各种不同的检索需求,本文介绍Mybatis如何优化检索,需要的朋友可以参考下
1.SQL 映射
- MyBatis 允许开发者直接编写原生SQL或动态SQL,而不是依赖于ORM框架生成的SQL
- 这种方式可以精确控制SQL执行,优化查询语句的性能,尤其是在处理复杂查询时
- 示例:
- 1-数据库表结构
- 假设有两个表:
user和role,以及一个关联表user_role
CREATE TABLE user (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
email VARCHAR(255)
);
CREATE TABLE role (
id INT AUTO_INCREMENT PRIMARY KEY,
role_name VARCHAR(255)
);
CREATE TABLE user_role (
user_id INT,
role_id INT,
FOREIGN KEY (user_id) REFERENCES user(id),
FOREIGN KEY (role_id) REFERENCES role(id)
);
- 2-MyBatis 配置文件(mybatis-config.xml)
- 这是 MyBatis 的全局配置文件,设置了一些基本配置和环境信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
- 3-Mapper XML 文件(UserMapper.xml)
- 这个文件定义了 SQL 映射和操作数据库的方法
<?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.example.mapper.UserMapper">
<select id="selectUserById" resultType="com.example.model.User">
SELECT * FROM user WHERE id = #{id}
</select>
<resultMap id="userRoleMap" type="com.example.model.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<collection property="roles" ofType="com.example.model.Role">
<id column="role_id" property="id"/>
<result column="role_name" property="roleName"/>
</collection>
</resultMap>
<select id="selectUserWithRoles" resultMap="userRoleMap">
SELECT u.id, u.username, r.id AS role_id, r.role_name
FROM user u
LEFT JOIN user_role ur ON u.id = ur.user_id
LEFT JOIN role r ON ur.role_id = r.id
WHERE u.id = #{id}
</select>
</mapper>
2.结果映射
- MyBatis 提供了高度灵活的结果映射机制,可以将数据库结果直接映射到复杂的对象模型中
- 它允许你将 SQL 查询返回的结果集映射到 Java 对象中
- 这减少了数据转换和处理的开销,使得数据加载更为高效
- 示例:
- 在 MyBatis 的 Mapper XML 中配置一个简单的结果映射如下:
<!-- Mapper XML 配置 -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 定义结果映射 -->
<resultMap id="BaseResultMap" type="com.example.model.User">
<id column="id" property="id" />
<result column="username" property="username" />
<result column="email" property="email" />
</resultMap>
<!-- 使用定义好的结果映射查询用户 -->
<select id="selectUserById" resultMap="BaseResultMap">
SELECT id, username, email FROM user WHERE id = #{id}
</select>
</mapper>
- 在这个例子中
BaseResultMap定义了如何将user表的列id、username、和email映射到 Java 对象User的相应属性中
3.延迟加载
- MyBatis 支持延迟加载技术,允许按需加载关联对象
- 这意味着只有在使用到某个关联对象时,才会执行相应的SQL查询
- 这种策略可以显著减少初始化对象时的数据库访问次数和网络延迟
- MyBatis 支持延迟加载的配置可以在
mybatis-config.xml中设置,例如:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
- 这个配置确保了只有在实际需要使用用户的角色信息时,才会去数据库加载角色数据
- 这种延迟加载可以提高应用的性能,特别是当数据结构复杂或数据量大时
4.缓存支持
- MyBatis 内置了强大的缓存机制,用于存储已经执行过的查询结果
- 以便在后续相同的查询请求中快速返回结果而无需再次执行实际的数据库查询
- 包括一级缓存(会话缓存)和二级缓存(全局缓存)
- 一级缓存默认开启,保证了同一会话中相同查询的结果可以被复用
- 而二级缓存则可以跨会话复用查询结果,减少数据库的查询次数,提高应用性能
一级缓存(Session Cache):
- 作用范围:一级缓存是基于 SQL 会话的,它仅在当前会话内有效
- 当会话关闭或提交时,一级缓存也会被清除
- 实现方式:默认情况下,MyBatis 的每个 SQL 会话有自己的一级缓存
- 每当会话中执行查询时,MyBatis 首先检查缓存中是否已存在相应的结果
- 如果有,则直接返回缓存结果;如果没有,则执行数据库查询并将查询结果放入缓存
- 缓存内容:缓存的内容包括查询结果对象和执行过的查询语句
二级缓存(Global Cache):
- 作用范围:二级缓存是跨会话的,它可以被不同的会话共享
- 二级缓存的作用范围通常是映射器(Mapper)级别,不同的映射器持有各自的二级缓存
- 配置方式:二级缓存需要在 MyBatis 配置文件或映射文件中显式开启
- 开启后,查询结果可以跨会话重用,从而减少对数据库的查询次数,提高效率
- 实现技术:二级缓存可以使用 MyBatis 自带的简单实现,也可以集成更强大的缓存解决方案,如 Ehcache、Redis 等
示例配置:
- 在 MyBatis 的 Mapper XML 中开启二级缓存的示例:
<!-- 开启当前 Mapper 的二级缓存 --> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
缓存策略:
- eviction:缓存的回收策略
- 常用的有
LRU(Least Recently Used 最少使用策略)、FIFO(First In First Out 先进先出策略)等 - flushInterval:缓存刷新间隔,单位是毫秒
- 设置后,缓存会在指定的时间间隔后自动清空
- size:引用数目,设置缓存中可以存储多少个对象
- readOnly:是否只读
- 如果为
true,则所有获取的缓存对象都是只读的,这样可以提供一些性能优势
5.批量操作优化
- MyBatis 提供了批处理的支持,允许在一个会话中执行多个更新操作
- 这可以减少数据库交互次数,降低网络开销和数据库压力
6.动态 SQL
- MyBatis 的动态SQL功能允许构建在运行时评估的SQL语句,根据不同的条件组装不同的SQL片段
- 这不仅提高了SQL的灵活性,也避免了不必要的查询条件,从而优化了查询效率
- 动态 SQL 的关键组件:
- 1-
<if>标签: - 根据条件是否为真来决定是否包含某个 SQL 片段
- 这可以用来添加可选的查询条件或修改其他 SQL 构造
- 2-
<choose>,<when>,<otherwise>标签: - 类似于 Java 中的
switch语句,根据多个条件选择性地包括 SQL 片段 - 3-
<where>标签: - 自动处理 SQL 查询中的
WHERE子句,如果其内部的条件为真,就插入WHERE关键字 - 同时也智能地处理多余的
AND或OR关键字 - 4-
<set>标签: - 用于动态构建
UPDATE语句,自动处理列赋值的列表,并且在需要时智能插入逗号 - 5-
<foreach>标签: - 用于在 SQL 语句中构建重复的 SQL 片段,如批量插入数据或构建
IN子句 - 6-
<sql>和<include>标签: - 用于SQL片段的抽取
<sql>:抽取SQL语句的标签<sql id="片段唯一标识">抽取的SQL语句</sql><include>:引入SQL片段标签<include refid="片段唯一标识" />- 示例:
- 以下是一些动态 SQL 的示例,展示如何在 MyBatis 的 Mapper XML 中使用它们
<!-- Mapper XML 文件中的示例 -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 动态生成 SELECT 查询 -->
<select id="findUsersByConditions" resultType="User">
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>
<!-- 动态生成 UPDATE 查询 -->
<update id="updateUser">
UPDATE users
<set>
<if test="username != null">
username = #{username},
</if>
<if test="email != null">
email = #{email},
</if>
</set>
WHERE id = #{id}
</update>
<!-- 使用 foreach 生成 IN 子句 -->
<select id="findUsersByIds" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach item="id" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>
7.插件和拦截器
- MyBatis 允许使用插件对查询过程进行拦截和修改
- 开发者可以通过插件来添加或改写某些操作的行为
- 如执行查询前的参数处理或执行后的结果处理,进一步优化查询性能
- MyBatis 插件本质上是通过拦截器(Interceptor)实现的
- MyBatis 的拦截器是实现了 Interceptor 接口的组件,用于在SQL执行的关键环节插入自定义逻辑
以上就是Mybatis优化检索的方法详解的详细内容,更多关于Mybatis优化检索的资料请关注脚本之家其它相关文章!
