MyBatis 底层原理深度解析

MyBatis 底层原理深度解析

一、整体架构设计

MyBatis 采用分层架构设计,核心模块如下:

SqlSession
Executor
StatementHandler
DataSource
Transaction
接口层
核心处理层
基础支撑层
应用程序
SQL执行
SQL处理
数据库连接
事务管理
1. 分层架构
  • 接口层:提供API(SqlSession、Mapper接口)
  • 核心处理层:SQL解析、参数映射、SQL执行、结果映射
  • 基础支撑层:连接管理、事务管理、缓存、日志等
2. 核心组件协作
应用程序SqlSessionExecutorStatementHandlerParameterHandlerResultSetHandlerDB调用Mapper方法执行请求创建Statement设置参数执行SQL返回结果集处理结果映射返回结果返回Java对象应用程序SqlSessionExecutorStatementHandlerParameterHandlerResultSetHandlerDB

二、核心组件详解

1. SqlSession
  • 作用:MyBatis 核心操作接口
  • 实现类DefaultSqlSession
  • 关键功能
    public interface SqlSession extends Closeable {
        <T> T selectOne(String statement);
        <E> List<E> selectList(String statement);
        int insert(String statement);
        int update(String statement);
        int delete(String statement);
        void commit();
        void rollback();
        <T> T getMapper(Class<T> type);
    }
    
2. Executor(执行器)
  • 类型

    • SimpleExecutor:默认执行器(每次请求创建新Statement)
    • ReuseExecutor:重用预处理Statement
    • BatchExecutor:批量操作优化
    • CachingExecutor:二级缓存装饰器
  • 执行流程

    public class SimpleExecutor extends BaseExecutor {
        public <E> List<E> query(...) {
            Statement stmt = null;
            try {
                Configuration config = context.getConfiguration();
                // 1. 获取MappedStatement
                MappedStatement ms = config.getMappedStatement(statement);
                
                // 2. 创建StatementHandler
                StatementHandler handler = config.newStatementHandler(..., ms, ...);
                
                // 3. 准备Statement
                stmt = prepareStatement(handler);
                
                // 4. 执行查询
                return handler.query(stmt, resultHandler);
            } finally {
                closeStatement(stmt);
            }
        }
    }
    
3. MappedStatement
  • 作用:存储SQL映射信息(XML/注解配置的SQL)
  • 关键属性
    public final class MappedStatement {
        private String id;
        private SqlSource sqlSource;
        private SqlCommandType sqlCommandType;
        private Class<?> parameterType;
        private Class<?> resultType;
        private ResultMap resultMap;
        // ...
    }
    
4. SqlSource & BoundSql
  • SqlSource:SQL源(动态/静态SQL)
    • DynamicSqlSource:含动态标签(if/foreach)
    • RawSqlSource:纯静态SQL
  • BoundSql:最终执行的SQL和参数
    public class BoundSql {
        private final String sql;             // 解析后的SQL
        private final List<ParameterMapping> parameterMappings;
        private final Object parameterObject; // 参数对象
        // ...
    }
    

三、SQL执行流程深度解析

1. SQL解析过程
动态SQL
静态SQL
MappedStatement
SqlSource
DynamicSqlSource
RawSqlSource
解析OGNL表达式
生成BoundSql
执行SQL
2. 参数映射原理
  • ParameterHandler:处理参数映射
    public class DefaultParameterHandler implements ParameterHandler {
        public void setParameters(PreparedStatement ps) {
            // 遍历参数映射
            for (ParameterMapping paramMapping : parameterMappings) {
                Object value;
                String propertyName = paramMapping.getProperty();
                
                // 获取参数值(通过反射或TypeHandler)
                if (parameterObject == null) {
                    value = null;
                } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                    value = parameterObject;
                } else {
                    // 使用MetaObject获取嵌套属性值
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    value = metaObject.getValue(propertyName);
                }
                
                // 获取TypeHandler设置参数
                TypeHandler typeHandler = paramMapping.getTypeHandler();
                typeHandler.setParameter(ps, i + 1, value, paramMapping.getJdbcType());
            }
        }
    }
    
3. 结果集映射
  • ResultSetHandler:处理结果映射
    public class DefaultResultSetHandler implements ResultSetHandler {
        public List<Object> handleResultSets(Statement stmt) throws SQLException {
            // 1. 获取ResultMap
            ResultMap resultMap = mappedStatement.getResultMap();
            
            // 2. 遍历结果集
            while (rs.next()) {
                Object resultObject = createResultObject(rs, resultMap);
                
                // 3. 应用自动映射
                applyAutomaticMappings(rs, resultObject);
                
                // 4. 应用显式映射
                applyPropertyMappings(rs, resultObject);
                
                resultList.add(resultObject);
            }
            return resultList;
        }
    }
    

四、缓存机制实现原理

1. 一级缓存(Local Cache)
  • 范围:SqlSession级别
  • 实现类PerpetualCache (使用HashMap)
  • 失效场景
    • 执行update操作(insert/update/delete)
    • 手动调用clearCache()
    • 配置flushCache=true
    • 提交事务(commit)或回滚(rollback)
2. 二级缓存(Global Cache)
  • 范围:Mapper(namespace)级别
  • 启用条件
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    
    <mapper namespace="com.example.UserMapper">
        <cache/> <!-- 启用二级缓存 -->
    </mapper>
    
  • 实现原理
    CachingExecutor
    TransactionalCache
    装饰器模式
    PerpetualCache
3. 缓存执行顺序
命中
未命中
命中
未命中
二级缓存
返回结果
一级缓存
返回结果
数据库查询
存入一级缓存
存入二级缓存

五、动态SQL解析机制

1. 解析流程
public class XMLScriptBuilder {
    protected SqlSource parseDynamicTags(XNode node) {
        // 1. 解析SQL片段
        List<SqlNode> contents = parseDynamicTags(node);
        
        // 2. 创建MixedSqlNode
        MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
        
        // 3. 创建SqlSource
        if (isDynamic) {
            return new DynamicSqlSource(config, rootSqlNode);
        } else {
            return new RawSqlSource(config, rootSqlNode, parameterType);
        }
    }
}
2. SqlNode实现
SqlNode类型对应标签功能
IfSqlNode<if>条件判断
ForEachSqlNode<foreach>循环遍历
TrimSqlNode<trim>自定义字符串截取
WhereSqlNode<where>自动处理WHERE条件
SetSqlNode<set>自动处理SET更新语句
TextSqlNode文本处理包含${}的动态文本

六、插件机制(Interceptor)

1. 拦截点(4大对象)
  • Executor(update/query/commit/rollback)
  • ParameterHandler(参数处理)
  • ResultSetHandler(结果集处理)
  • StatementHandler(SQL准备)
2. 实现原理(责任链模式)
目标对象
Plugin代理
Interceptor1
Interceptor2
原始对象
3. 自定义插件示例
@Intercepts({
    @Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
    )
})
public class QueryInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = invocation.proceed(); // 执行原方法
        long end = System.currentTimeMillis();
        System.out.println("SQL执行耗时: " + (end - start) + "ms");
        return result;
    }
    
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this); // 创建代理
    }
}

七、Mapper接口绑定原理

1. 动态代理实现
public class MapperProxy<T> implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 1. 解析MapperMethod
        MapperMethod mapperMethod = cachedMapperMethod(method);
        
        // 2. 执行SQL命令
        return mapperMethod.execute(sqlSession, args);
    }
}

public class MapperMethod {
    public Object execute(SqlSession sqlSession, Object[] args) {
        switch (command.getType()) {
            case SELECT: 
                return sqlSession.selectOne(command.getName(), param);
            case INSERT:
                return sqlSession.insert(command.getName(), param);
            // ...
        }
    }
}
2. 方法签名解析
public class MapperMethod {
    public static class MethodSignature {
        public MethodSignature(Configuration config, Method method) {
            // 解析返回类型
            this.returnType = method.getReturnType();
            
            // 解析参数
            this.params = getParams(method);
            
            // 解析@Param注解
            this.paramNameResolver = new ParamNameResolver(config, method);
        }
    }
}

八、性能优化关键点

  1. Statement重用:使用ReuseExecutor
  2. 批量操作:使用BatchExecutor
  3. 分页优化:避免内存分页(使用物理分页)
  4. 结果集控制
    <!-- 关闭自动映射 -->
    <setting name="autoMappingBehavior" value="NONE"/>
    
  5. 延迟加载
    <setting name="lazyLoadingEnabled" value="true"/>
    

九、设计模式应用

设计模式应用场景实现类
建造者模式配置对象创建SqlSessionFactoryBuilder
工厂模式SqlSession创建SqlSessionFactory
代理模式Mapper接口实现MapperProxy
装饰器模式缓存实现CachingExecutor
责任链模式插件拦截器InterceptorChain
模板方法模式执行器操作流程BaseExecutor

十、与JDBC对比优势

特性原生JDBCMyBatis
连接管理手动创建/关闭自动池化管理
SQL编写Java硬编码XML/注解分离管理
参数绑定手动setParameter自动映射
结果映射手动遍历ResultSet自动对象映射
缓存机制无内置缓存一级/二级缓存
事务控制手动commit/rollback声明式事务管理
扩展性插件机制扩展

总结:MyBatis 核心优势

  1. SQL控制灵活:原生SQL编写能力
  2. 映射智能化:自动参数绑定与结果映射
  3. 架构解耦:SQL与Java代码分离
  4. 缓存优化:多级缓存提升性能
  5. 扩展性强:插件机制支持深度定制
  6. 轻量级:无侵入式设计,依赖少

深入理解MyBatis底层原理的关键点:

  • 动态代理:Mapper接口实现机制
  • SQL解析:动态SQL生成过程
  • 缓存体系:二级缓存实现原理
  • 插件扩展:责任链拦截机制
  • 执行流程:四大核心组件协作

通过分析源码(重点包:org.apache.ibatis.executororg.apache.ibatis.mappingorg.apache.ibatis.scripting)可进一步加深对MyBatis运行机制的理解。

MyBatis 是一款优秀的持久层框架,其核心目标是通过简化 JDBC 操作实现 Java 对象与数据库表的映射(ORM),让开发者更高效地操作数据库。它的底层原理围绕核心组件协作SQL 执行流程ORM 映射机制缓存优化展开。以下从底层架构、关键组件、执行流程到高级特性,全面解析 MyBatis 的底层原理。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值