news 2026/7/22 15:49:18

MyBatis核心流程以及工作原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MyBatis核心流程以及工作原理

MyBatis核心对象

  • 根据以下这四大核心对象,我们就能理清MyBatis的工作原理。

  1. SqlSession对象,该对象中包含了执行SQL语句的所有方法。类似于JDBC里面的Connection。

  1. Executor接口,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。

  1. MappedStatement对象,该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。

  1. ResultHandler对象,用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回类型。

MyBatis工作原理

  • 上面中流程就是MyBatis内部核心流程,每一步流程的详细说明如下文所述:

  1. 读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。

  1. 加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

  1. 构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。

  1. 创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。

  1. Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。

  1. MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。

  1. 输入参数映射。输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。

  1. 输出结果映射。输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。

注意:在MyBatis中,SqlSession对象包含了执行SQL语句的所有方法。但是它是委托Executor执行的。从某种意义上来看,MyBatis里面的SqlSession类似于JDBC中的Connection,它们都是委托给其它类去执行。

MyBatis整合Log4j框架

  • Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:

SLF4J

Apache Commons Logging

Log4j 2

Log4j

JDK logging

  • sqlSession.close();MyBatis 内置日志工厂会基于运行时检测信息选择日志委托实现。它会(按上面罗列的顺序)使用第一个查找到的实现。当没有找到这些实现时,将会禁用日志功能。

  1. 通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting来选择其它日志实现。这里以log4j为例。

<configuration> <settings> ... <setting name="logImpl" value="LOG4J"/> ... </settings> </configuration>
  1. 配置log4j,假设你需要记录这个映射器的日志:

package com.xyr.dao; import com.xyr.domain.User; import org.apache.ibatis.annotations.Select; public interface UserMapper { @Select("select * from user where id = #{id}") User selectUserById(Integer id); }

在应用的类路径中创建一个名为 log4j.properties 的文件,文件的具体内容如下:

# 全局日志配置 log4j.rootLogger=ERROR, stdout # MyBatis 日志配置 log4j.logger.com.xyr.dao.UserMapper=TRACE # 控制台输出 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

实现结果如下:

上述配置将使 Log4J 详细打印 com.xyr.dao.UserMapper 的日志,对于应用的其它部分,只打印错误

信息。

  • 为了实现更细粒度的日志输出,你也可以只打印特定语句的日志。以下配置将只打印语句selectUserById 的日志:

log4j.logger.com.xyr.dao.UserMapper.selectUserById=TRACE
  • 为了实现更粗粒度的日志输出,你也可以打印所有mapper的日志。以下配置将只打印所有mapper 的日志:

log4j.logger.com.xyr.dao=TRACE
  • 在实际开发中往往查出来的数据经常可能会有成百上千条,如果希望不显示查询出来的数据,让控制台更加清晰,可以设置日志的显示级别,设置为DEBUG级别可以不显示查询结果,如下所示:

log4j.logger.com.xyr.dao.UserMapper=DEBUG

注意:为映射器和 XML 文件打开日志功能的语句毫无差别。

MyBatis基于XML配置实现CRUD

引入自定义代码工具类MyBatisUtils

package com.xyr.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; /** * @Title 针对MyBatis框架的一些固定步骤进行二次封装 * @Author zhk * @Description: */ public class MyBatisUtils { private static SqlSessionFactory factory; private MyBatisUtils() {} static { try { InputStream is = Resources.getResourceAsStream("mybatisconfig.xml"); factory = new SqlSessionFactoryBuilder().build(is); } catch (Exception e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return factory.openSession(); } public static void close(SqlSession session) { if (Objects.nonNull(session)) { session.close(); } } }

SqlSession默认不自动提交事务,可使用sqlSessionFactory.openSession(true); 来自动提交事务。

添加操作

添加用户记录

UserMapper类代码如下所示:

public interface UserMapper { int insertUser(User u); }

UserMapper.xml配置如下所示:

<insert id="insertUser" parameterType="com.xyr.domain.User"> insert into user(name, password, age) values(#{name}, #{password}, #{age}) </insert>

测试代码如下所示:

package com.xyr.dao; import com.xyr.domain.User; import com.xyr.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; /** * @Title * @Author Xyr * @Description: */ public class UserMapperTest { private SqlSession sqlSession; private UserMapper mapper; @Before public void init() { sqlSession = MyBatisUtils.getSqlSession(); mapper = sqlSession.getMapper(UserMapper.class); } @After public void destroy() { MyBatisUtils.close(sqlSession); } @Test public void testInsert() { User u = new User(); u.setName("张三"); u.setPassword("123456"); u.setAge(18); mapper.insertUser(u); sqlSession.commit(); } }

注意:添加操作属于DML语句,针对DML语句需要进行事务的提交,所以需要手动调用sqlSession对象的commit方法进行显示提交。

主键回填

在增加操作中,如果设置了主键id是自增的,那么插入数据时id的值一般写null,因为存入数据库时id都会自动+1,看似操作没毛病,非常完美。

但是在购物交易的添加模块这可不兴这样,细想一下在上网买东西时,用户付完钱之后一般都会返回一个订单编号,其实这个订单编号在数据库中就是主键,但是因为在插入数据时id的值写了null,所以订单编号也为null,也就是说返回不了订单编号的数据。

方式一:使用 useGeneratedKeys 属性

<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into user(name, password, age) values(#{name}, #{password}, #{age}) </insert>

方式二:使用 selectKey 标签

<insert id="insertUser" parameterType="User"> <selectKey keyProperty="id" keyColumn="id" resultType="java.lang.Integer" order="AFTER"> select last_insert_id() </selectKey> insert into user(name, password, age) values(#{name}, #{password}, #{age}) </insert>
  • 如果id的值是字符串类型的uuid时,数据库就不能够主键自动生成,那么可以考虑使用方式二来实现

<insert id="insertUser2" parameterType="com.xyr.domain.User2"> <selectKey resultType="java.lang.String" keyColumn="id" keyProperty="id" order="BEFORE"> select uuid(); </selectKey> insert into t_user(id, name, password, age) values(#{id}, #{name}, #{password}, #{age}) </insert>

详细请参考: Mybatis---主键回填 (*^▽^*)_数据库_Lynn Lu-DevPress官方社区 (csdn.net)

删除操作

通过id删除用户记录

更新操作

通过id更新用户记录

测试代码如下:

@Test public void testUpdate() { User u = new User(); u.setId(11); u.setName("宋小宝"); u.setPassword("666666"); u.setAge(30); mapper.updateUserById(u); sqlSession.commit(); }

查询操作

通过id查询单个用户

查询所有用户

测试代码如下:

@Test public void testSelectAllUsers() { mapper.selectAllUsers(); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 15:45:06

金属加工核心人才留不住?北京华恒智信薪酬优化成功案例

【客户行业】生产制造行业【问题类型】薪酬改革【客户背景及现状】某大型金属加工公司隶属于大型央企集团&#xff0c;至今成立已有60余年。公司主导业务是进行某有色金属的生产加工&#xff0c;其产品广泛应用于电子通讯、轨道交通、航空航天、国防军工、船舶制造等高端领域&a…

作者头像 李华
网站建设 2026/7/22 15:42:22

AI提效秘籍:如何让员工效率提升真正为组织赋能,附收藏攻略!

本文探讨了企业内部AI使用调研发现的问题&#xff1a;员工个人效率提升并未转化为组织效率提升。分析了原因在于个人与组织效率目标不同&#xff0c;以及企业未能建立有效的“人效飞轮”机制。提出了解决方案&#xff1a;引导员工将AI节省的时间用于高价值工作&#xff0c;实现…

作者头像 李华
网站建设 2026/7/22 15:30:27

CI/CD 中的密钥注入方案:SOPS、Sealed Secrets 与 Vault

CI/CD 中的密钥注入方案&#xff1a;SOPS、Sealed Secrets 与 Vault 一、你的数据库密码躺在 Git 仓库里&#xff0c;而安全意识开会还要等三周 CI/CD 流水线里最让人头疼的不是构建失败&#xff0c;不是测试超时&#xff0c;而是密钥管理。数据库密码、API Key、证书私钥——这…

作者头像 李华
网站建设 2026/7/22 15:29:17

TI TMS320TCI6484/C6457 DSP硬件设计:电源、时钟与配置实战指南

1. 项目概述在通信基站、雷达信号处理或者高性能计算卡这类对实时性和算力要求极高的领域&#xff0c;德州仪器&#xff08;TI&#xff09;的TMS320TCI6484和TMS320C6457这两款多核数字信号处理器&#xff08;DSP&#xff09;是许多资深硬件工程师的老朋友了。它们凭借强大的并…

作者头像 李华