本文共 6042 字,大约阅读时间需要 20 分钟。
MyBatis是一款流行的持久层框架,支持定制化SQL、存储过程及高级映射。它通过减少JDBC代码,避免手动设置参数和结果集的操作,为开发者提供了更加简洁高效的数据访问方式。MyBatis可以使用XML或注解配置,支持原生类型、接口及Java POJO与数据库记录的映射。
MyBatis的核心配置通常存储在mybatis-config.xml中,主要包含以下要素:
UserMapper.xml是典型的MyBatis SQL映射文件,用于定义具体的数据库操作。例如:
MyBatis通过数据源和事务管理器与数据库进行连接,支持多种数据库事务管理方式。默认使用JDBC数据源配置,确保数据库连接的稳定性和高效性。
configuration.getMappedStatement(statement)获取对应的SQL映射信息。#{id})。resultType)处理结果集,返回相应的对象或数据集合。MyBatis提供了一级缓存机制,通过CacheKey生成唯一的缓存键。缓存键由以下信息构成:
<id>rowBoundsboundSql.getSql()createCacheKey方法处理后的参数值缓存机制的作用是减少数据库查询次数,提升应用性能。
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);} Configuration对象。configuration节点,初始化其他配置元素。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); }} publicT 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;}
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;} public Listquery(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);}
通过源码解析,我们可以清晰地看到MyBatis的工作原理。从配置文件读取到SQL执行,再到缓存机制的应用,MyBatis通过高度的抽象化和优化,显著提升了数据库访问的效率和开发体验。如果你对数据库开发感兴趣,掌握MyBatis将是非常有价值的。
转载地址:http://nmvuz.baihongyu.com/