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

01-MyBatis核心详解

MyBatis核心详解

一、知识概述

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects)为数据库中的记录。

本文将深入讲解 MyBatis 的核心原理,包括 SqlSession 的生命周期、Mapper 代理机制、缓存机制等,帮助你理解 MyBatis 的工作原理,更好地使用和优化 MyBatis。

二、核心组件详解

2.1 MyBatis 整体架构

┌─────────────────────────────────────────────────────────────┐ │ 应用程序层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Mapper 接口 │ │ Service 层 │ │ Controller │ │ │ └──────┬──────┘ └──────┬──────┘ └─────────────┘ │ └─────────┼────────────────┼──────────────────────────────────┘ │ │ ┌─────────┼────────────────┼──────────────────────────────────┐ │ ▼ ▼ MyBatis 框架层 │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ SqlSession │ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ Configuration │ │ Executor │ │ │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ StatementHan │ │ ParameterHan │ │ │ │ │ │ dler │ │ dler │ │ │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ ResultSetHan │ │ TypeHandler │ │ │ │ │ │ dler │ │ │ │ │ │ │ └──────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 数据库层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ MySQL │ │ Oracle │ │ PostgreSQL │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────┘

2.2 核心组件介绍

/** * MyBatis 核心组件层次结构 * * SqlSessionFactoryBuilder → SqlSessionFactory → SqlSession → Mapper * * 每个组件的职责: * 1. SqlSessionFactoryBuilder: 解析配置,构建 SqlSessionFactory * 2. SqlSessionFactory: 创建 SqlSession 的工厂(单例) * 3. SqlSession: 执行 SQL 的会话(非线程安全,每次请求创建) * 4. Mapper: 接口代理,执行具体 SQL */publicclassMyBatisCoreComponents{publicstaticvoidmain(String[]args){// 1. SqlSessionFactoryBuilder - 构建 SqlSessionFactory// 生命周期:方法局部,用完即弃SqlSessionFactoryBuilderbuilder=newSqlSessionFactoryBuilder();// 2. SqlSessionFactory - 工厂单例// 生命周期:应用级别,整个应用运行期间存在// 最佳实践:通过单例模式或 Spring 容器管理SqlSessionFactorysqlSessionFactory=builder.build(Resources.getResourceAsStream("mybatis-config.xml"));// 3. SqlSession - 数据库会话// 生命周期:请求/方法级别,非线程安全// 最佳实践:每次数据库操作创建,用完关闭try(SqlSessionsession=sqlSessionFactory.openSession()){// 4. Mapper 接口 - 执行 SQL// 生命周期:随 SqlSession,每次获取新实例UserMappermapper=session.getMapper(UserMapper.class);Useruser=mapper.selectById(1L);System.out.println(user);}}}

2.3 配置详解

<!-- mybatis-config.xml - MyBatis 核心配置文件 --><?xml version="1.0" encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 1. 属性配置 - 可从外部文件加载 --><propertiesresource="db.properties"><propertyname="username"value="root"/><propertyname="password"value="123456"/></properties><!-- 2. 设置 - 全局配置参数 --><settings><!-- 开启驼峰命名自动映射 --><settingname="mapUnderscoreToCamelCase"value="true"/><!-- 开启二级缓存 --><settingname="cacheEnabled"value="true"/><!-- 延迟加载全局开关 --><settingname="lazyLoadingEnabled"value="true"/><!-- 设置超时时间 --><settingname="defaultStatementTimeout"value="30"/><!-- 日志实现 --><settingname="logImpl"value="SLF4J"/></settings><!-- 3. 类型别名 - 为 Java 类型设置缩写 --><typeAliases><!-- 单个类别名 --><typeAliastype="com.example.entity.User"alias="User"/><!-- 包扫描别名(默认首字母小写) --><packagename="com.example.entity"/></typeAliases><!-- 4. 类型处理器 - 自定义类型转换 --><typeHandlers><typeHandlerjavaType="java.util.Date"handler="com.example.handler.DateTypeHandler"/></typeHandlers><!-- 5. 插件 - 拦截器 --><plugins><plugininterceptor="com.example.plugin.MyPlugin"><propertyname="someProperty"value="100"/></plugin></plugins><!-- 6. 环境配置 --><environmentsdefault="development"><environmentid="development"><!-- 事务管理器 --><transactionManagertype="JDBC"/><!-- 数据源 --><dataSourcetype="POOLED"><propertyname="driver"value="${driver}"/><propertyname="url"value="${url}"/><propertyname="username"value="${username}"/><propertyname="password"value="${password}"/><!-- 连接池配置 --><propertyname="poolMaximumActiveConnections"value="20"/><propertyname="poolMaximumIdleConnections"value="10"/><propertyname="poolMaximumCheckoutTime"value="20000"/></dataSource></environment></environments><!-- 7. 数据库厂商标识 --><databaseIdProvidertype="DB_VENDOR"><propertyname="MySQL"value="mysql"/><propertyname="Oracle"value="oracle"/></databaseIdProvider><!-- 8. 映射器配置 --><mappers><!-- 使用 XML 配置 --><mapperresource="mapper/UserMapper.xml"/><!-- 使用接口配置 --><mapperclass="com.example.mapper.UserMapper"/><!-- 包扫描 --><packagename="com.example.mapper"/></mappers></configuration>

三、SqlSession 源码解析

3.1 SqlSession 创建过程

/** * SqlSession 创建流程源码分析 */publicclassSqlSessionCreationAnalysis{/** * SqlSessionFactory 接口定义 */publicinterfaceSqlSessionFactory{// 创建默认 SqlSession(非自动提交)SqlSessionopenSession();// 创建指定自动提交的 SqlSessionSqlSessionopenSession(booleanautoCommit);// 使用指定 Connection 创建 SqlSessionSqlSessionopenSession(Connectionconnection);// 指定事务隔离级别SqlSessionopenSession(TransactionIsolationLevellevel);// 指定执行器类型SqlSessionopenSession(ExecutorTypeexecType);}/** * DefaultSqlSessionFactory.openSession() 实现 */publicclassDefaultSqlSessionFactoryimplementsSqlSessionFactory{privatefinalConfigurationconfiguration;@OverridepublicSqlSessionopenSession(){returnopenSessionFromDataSource(configuration.getDefaultExecutorType(),// 执行器类型configuration.getDefaultTransactionIsolationLevel(),// 事务隔离级别false// 自动提交);}privateSqlSessionopenSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,booleanautoCommit){Transactiontx=null;try{// 1. 从 Configuration 获取 Environment(包含数据源和事务配置)finalEnvironmentenvironment=configuration.getEnvironment();// 2. 创建事务TransactionFactorytransactionFactory=getTransactionFactoryFromEnvironment(environment);tx=transactionFactory.newTransaction(environment.getDataSource(),level,autoCommit);// 3. 创建执行器(关键!)Executorexecutor=configuration.newExecutor(tx,execType);// 4. 创建 DefaultSqlSessionreturnnewDefaultSqlSession(configuration,executor,autoCommit);}catch(Exceptione){closeTransaction(tx);throwExceptionFactory.wrapException("Error opening session. Cause: "+e,e);}}}}

3.2 SqlSession 执行流程

/** * SqlSession 执行 SQL 的完整流程 */publicclassSqlSessionExecutionFlow{publicstaticvoidmain(String[]args){SqlSessionFactoryfactory=SqlSessionFactoryBuilder.build(...);try(SqlSessionsession=factory.openSession()){// 查询操作Useruser=session.selectOne("com.example.mapper.UserMapper.selectById",1L);// 插入操作introws=session.insert("com.example.mapper.UserMapper.insert",user);// 更新操作introws=session.update("com.example.mapper.UserMapper.update",user);// 删除操作introws=session.delete("com.example.mapper.UserMapper.deleteById",1L);// 提交事务(如果非自动提交)session.commit();}}/** * DefaultSqlSession.selectOne 源码 */publicclassDefaultSqlSessionimplementsSqlSession{privatefinalConfigurationconfiguration;privatefinalExecutorexecutor;@Overridepublic<T>TselectOne(Stringstatement,Objectparameter){// 调用 selectList,取第一个结果List<T>list=this.<T>selectList(statement,parameter);if(list.size()==1){returnlist.get(0);}elseif(list.size()>1){thrownewTooManyResultsException("Expected one result but found: "+list.size());}returnnull;}@Overridepublic<E>List<E>selectList(Stringstatement,Objectparameter){returnselectList(statement,parameter,RowBounds.DEFAULT);}@Overridepublic<E>List<E>selectList(Stringstatement,Objectparameter,RowBoundsrowBounds){try{// 1. 从 Configuration 获取 MappedStatementMappedStatementms=configuration.getMappedStatement(statement);// 2. 委托给 Executor 执行returnexecutor.query(ms,wrapCollection(parameter),rowBounds,Executor.NO_RESULT_HANDLER);}catch(Exceptione){throwExceptionFactory.wrapException("Error querying database. Cause: "+e,e);}}}}

四、Mapper 代理机制

4.1 Mapper 接口绑定

/** * Mapper 接口代理机制详解 * * MyBatis 通过 JDK 动态代理为 Mapper 接口创建代理对象 * 代理对象拦截方法调用,将其转换为 SQL 执行 */publicclassMapperProxyMechanism{/** * Mapper 接口定义 */publicinterfaceUserMapper{UserselectById(Longid);List<User>selectAll();intinsert(Useruser);intupdate(Useruser);intdeleteById(Longid);}/** * 对应的 XML 映射文件 *//* <?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 resultType="User"> SELECT * FROM user WHERE id = #{id} </select> <select resultType="User"> SELECT * FROM user </select> <insert parameterType="User"> INSERT INTO user(name, email, age) VALUES(#{name}, #{email}, #{age}) </insert> <update parameterType="User"> UPDATE user SET name=#{name}, email=#{email}, age=#{age} WHERE id=#{id} </update> <delete> DELETE FROM user WHERE id = #{id} </delete> </mapper> *//** * MapperProxy 核心源码分析 */publicclassMapperProxy<T>implementsInvocationHandler,Serializable{privatestaticfinallongserialVersionUID=-6424540398559729838L;privatefinalSqlSessionsqlSession;privatefinalClass<T>mapperInterface;privatefinalMap<Method,MapperMethod>methodCache;publicMapperProxy(SqlSessionsqlSession,Class<T>mapperInterface,Map<Method,MapperMethod>methodCache){this.sqlSession=sqlSession;this.mapperInterface=mapperInterface
http://www.cnnetsun.cn/news/1832195.html

相关文章:

  • 3分钟搞懂离散型三大分布:0-1、二项、泊松分布的实际应用场景
  • 3分钟搞定!免费虚拟显示器让游戏串流体验飙升的终极指南
  • 当JavaScript加密遇上Web3:用crypto-js重构数据安全新范式
  • Rust的const fn:编译期可执行的函数
  • Go语言的sync.RWMutex表现分析
  • Go微服务缓存策略:解决高频接口响应慢问题
  • 57-CubeMX-STM32F103RC-DAC
  • 告别连接失败!用QODBC驱动Qt应用读写MySQL数据库的完整配置流程与原理浅析
  • 【亲测免费】 PlugY - 您的暗黑破坏神II生存工具包
  • React 18终极兼容性指南:react-syntax-highlighter如何完美适配新特性
  • 2026届毕业生推荐的六大降AI率平台实测分析
  • MobaXterm全能终端:手机检测系统运维利器
  • Neuralangelo vs Instant NGP:3D重建技术深度对比与场景选择指南
  • SteamTinkerLaunch社区与支持:如何获取帮助和参与项目发展
  • Phi-4-mini-reasoning基础教程:如何构造高质量推理题输入提示词
  • MallChat分布式事务处理:安全调用与消息可靠性的终极保障
  • 如何高效使用C2Rust AST导出器:Clang抽象语法树提取与转换完整指南
  • 在超大数据集下 DuckDB 与 MySQL 查询速度对比凳
  • Pixel Couplet Gen 生成效果控制详解:关键参数对像素风格与文本内容的影响
  • SiameseUIE计算机网络应用:分布式信息抽取系统设计
  • ComfyUI ControlNet预处理器:解锁AI图像生成的控制艺术
  • GPU性能大比拼:cnn-benchmarks揭示Pascal vs Maxwell架构差异
  • ethers-rs高级交易技巧:Gas优化、Nonce管理和批量操作
  • Swift高性能计算库Surge终极指南:如何利用SIMD加速矩阵运算与信号处理
  • Nunchaku FLUX.1 CustomV3优化技巧:几个小设置,让你的图片生成效果更出色
  • Ostrakon-VL-8B效果实测:百种零售商品SKU识别精度报告
  • pandas-读取数据并显示,pd.read_csv,df.tail(5),df.shape,df.shape
  • Python使用PyEnchant详解:打造高效拼写检查工具
  • NaViL-9B图文问答入门:支持‘读取文字→分析颜色→总结布局’链式指令
  • 5分钟搞定B站视频解析:这款免费PHP工具让你轻松获取高清播放地址