博客
关于我
深入浅出mybatis
阅读量:424 次
发布时间:2019-03-06

本文共 6042 字,大约阅读时间需要 20 分钟。

MyBatis技术深入解析

MyBatis概述

MyBatis是一款流行的持久层框架,支持定制化SQL、存储过程及高级映射。它通过减少JDBC代码,避免手动设置参数和结果集的操作,为开发者提供了更加简洁高效的数据访问方式。MyBatis可以使用XML或注解配置,支持原生类型、接口及Java POJO与数据库记录的映射。

MyBatis配置与SQL编写

MyBatis配置文件

MyBatis的核心配置通常存储在mybatis-config.xml中,主要包含以下要素:

  • 环境配置:定义默认环境(如开发环境),配置数据源、事务管理器等。
  • 类型别名:定义常用类别的别名,便于在SQL中使用简化的命名。
  • 映射器配置:定义SQL映射,指定参数类型和结果类型。

SQL映射文件

UserMapper.xml是典型的MyBatis SQL映射文件,用于定义具体的数据库操作。例如:

数据库连接与事务管理

MyBatis通过数据源和事务管理器与数据库进行连接,支持多种数据库事务管理方式。默认使用JDBC数据源配置,确保数据库连接的稳定性和高效性。

MyBatis的内部原理

核心类解析

  • SqlSessionFactoryBuilder:负责读取MyBatis配置文件并构建SqlSessionFactory。
  • SqlSession:提供数据库操作的接口,包括查询、插入、更新、删除等操作。
  • DefaultSqlSession:SqlSession的默认实现类,负责执行数据库操作。
  • Executor:执行SQL语句的核心类,负责参数处理和结果集获取。

SQL执行过程

  • 获取映射信息:通过configuration.getMappedStatement(statement)获取对应的SQL映射信息。
  • 参数处理:将参数对象转换为可绑定的参数值,并生成参数占位符(如#{id})。
  • SQL拼接:根据绑定的参数值,动态拼接最终的SQL语句。
  • 结果集处理:根据结果类型(resultType)处理结果集,返回相应的对象或数据集合。
  • MyBatis缓存机制

    MyBatis提供了一级缓存机制,通过CacheKey生成唯一的缓存键。缓存键由以下信息构成:

    • SQL标识符:如<id>
    • 行偏移和限制rowBounds
    • SQL语句boundSql.getSql()
    • 参数值:通过createCacheKey方法处理后的参数值

    缓存机制的作用是减少数据库查询次数,提升应用性能。

    MyBatis源码解析

    SqlSessionFactoryBuilder

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    return build(parser.parse());
    } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    }
    }
    private SqlSessionFactory build(Configuration configuration) {
    return new SqlSessionFactoryImpl(configuration);
    }
    • XMLConfigBuilder:读取并解析MyBatis配置文件,生成Configuration对象。
    • parse():解析配置文件中的configuration节点,初始化其他配置元素。

    SqlSession.openSession()

    public SqlSession openSession() {
    return openSessionFromDataSource(null, null, false);
    }
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    try {
    Environment environment = this.configuration.getEnvironment();
    TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
    Transaction tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    Executor executor = this.configuration.newExecutor(tx, execType);
    return new DefaultSqlSession(this.configuration, executor, autoCommit);
    } catch (Exception e) {
    this.closeTransaction(tx);
    throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
    }
    }
    • newExecutor():根据事务管理器创建Executor实例,负责执行SQL语句。
    • DefaultSqlSession:负责管理数据库事务和执行SQL语句。

    SQL查询执行

    public 
    T selectOne(String statement, Object parameter) {
    List
    list = selectList(statement, parameter);
    if (list.size() == 1) {
    return list.get(0);
    } else if (list.size() > 1) {
    throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
    return null;
    }
    }
    public
    List
    selectList(String statement, Object parameter) {
    MappedStatement ms = this.configuration.getMappedStatement(statement);
    List
    list = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    return list;
    }
    • executor.query():执行实际的数据库查询,返回结果集合。
    • wrapCollection():将参数对象转换为适用于MyBatis执行器的参数集合。

    缓存机制细节

    public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    CacheKey cacheKey = new CacheKey();
    cacheKey.update(ms.getId());
    cacheKey.update(rowBounds.getOffset());
    cacheKey.update(rowBounds.getLimit());
    cacheKey.update(boundSql.getSql());
    List
    parameterMappings = boundSql.getParameterMappings();
    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
    for (ParameterMapping parameterMapping : parameterMappings) {
    if (parameterMapping.getMode() != ParameterMode.OUT) {
    String propertyName = parameterMapping.getProperty();
    Object value = null;
    if (boundSql.hasAdditionalParameter(propertyName)) {
    value = boundSql.getAdditionalParameter(propertyName);
    } else if (parameterObject == null) {
    value = null;
    } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
    value = parameterObject;
    } else {
    MetaObject metaObject = this.configuration.newMetaObject(parameterObject);
    value = metaObject.getValue(propertyName);
    }
    cacheKey.update(value);
    }
    }
    if (this.configuration.getEnvironment() != null) {
    cacheKey.update(this.configuration.getEnvironment().getId());
    }
    return cacheKey;
    }
    • cacheKey.update():根据参数值生成唯一的缓存键。
    • 参数映射:处理参数对象,获取对应的字段值,并更新缓存键。

    查询执行过程

    public List
    query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {
    Cache cache = ms.getCache();
    if (cache != null) {
    this.flushCacheIfRequired(ms);
    if (ms.isUseCache() && resultHandler == null) {
    this.ensureNoOutParams(ms, parameterObject, boundSql);
    List
    list = (List
    ) this.tcm.getObject(cache, key);
    if (list == null) {
    list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    this.tcm.putObject(cache, key, list);
    }
    return list;
    }
    }
    return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }
    • flushCacheIfRequired():根据缓存策略决定是否清除缓存。
    • ensureNoOutParams():确保没有输出参数(如存储过程返回值),避免缓存问题。
    • delegate.query():委派执行实际的数据库查询操作。

    总结

    通过源码解析,我们可以清晰地看到MyBatis的工作原理。从配置文件读取到SQL执行,再到缓存机制的应用,MyBatis通过高度的抽象化和优化,显著提升了数据库访问的效率和开发体验。如果你对数据库开发感兴趣,掌握MyBatis将是非常有价值的。

    转载地址:http://nmvuz.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现BellmanFord贝尔曼-福特算法(附完整源码)
    查看>>
    Objective-C实现BF算法 (附完整源码)
    查看>>
    Objective-C实现binary exponentiation二进制幂运算算法(附完整源码)
    查看>>
    Objective-C实现binomial coefficient二项式系数算法(附完整源码)
    查看>>
    Objective-C实现disjoint set不相交集算法(附完整源码)
    查看>>
    Objective-C实现DNF排序算法(附完整源码)
    查看>>
    Objective-C实现double factorial recursive双阶乘递归算法(附完整源码)
    查看>>
    Objective-C实现DoublyLinkedList双链表的算法(附完整源码)
    查看>>
    Objective-C实现Edmonds-Karp算法(附完整源码)
    查看>>
    Objective-C实现EEMD算法(附完整源码)
    查看>>
    Objective-C实现EM算法(附完整源码)
    查看>>
    Objective-C实现entropy熵算法(附完整源码)
    查看>>
    Objective-C实现euclidean distance欧式距离算法(附完整源码)
    查看>>
    Objective-C实现euclideanDistance欧氏距离算法(附完整源码)
    查看>>
    Objective-C实现euler method欧拉法算法(附完整源码)
    查看>>
    Objective-C实现eulerianPath欧拉路径算法(附完整源码)
    查看>>
    Objective-C实现eval函数功能(附完整源码)
    查看>>
    Objective-C实现Exceeding words超词(差距是ascii码的距离) 算法(附完整源码)
    查看>>
    Objective-C实现extended euclidean algorithm扩展欧几里得算法(附完整源码)
    查看>>
    Objective-C实现factorial iterative阶乘迭代算法(附完整源码)
    查看>>