背景介绍
Mybatis 是一个 Data Mapper Framework,属于 ORM 框架;旨在提供更简单,更方便地完成操作数据库功能,减轻开发⼈员的⼯作量,消除程序冗余代码。
功能框架
主要从功能⽅面配合源码进行解析 Mybatis 的实现过程和原理,功能框架图如下:
接⼝层:
-
使用 Mybatis 提供 API 操作数据库,传递 statementId 和参数 map 给 sqlSession;
-
使⽤ mapper 接⼝⽅式操作数据库,每个接⼝口⽅方法对应⼀一个 mapper 节点<insert/select/update/delete>;
处理层:
-
处理传入参数,同时进行类型转换 —— ParameterHandler 分析
-
根据传入参数,使⽤ ognl 动态生成 SQL 语句 —— StatementHandler 分析
-
将 SQL 语句和参数交于执行器进⾏获取结果 —— Executor 分析
-
处理结果集,类型转换 —— ResultSetHandler 分析
框架层:
-
数据源和连接池管理理 —— 数据源与连接池分析
-
事务管理理 —— 事务分析
-
缓存管理理(⼀级缓存和二级缓存) —— 缓存分析
-
SQL 语句配置⽅式管理(XML和注解) —— 配置⽅方式分析
Mybatis 中⽐较核心重要且常⽤的类:
- Configuration MyBatis 所有的配置信息都维持在 Configuration 对象之中。
- TypeHandler 负责 java 数据类型和 jdbc 数据类型之间的映射和转换。
- MappedStatement 维护了一条 <select|update|delete|insert> 节点的封装。
- StatementHandler 封装了 JDBC Statement 操作,负责对 JDBC statement 的操作,如设置参数、将 Statement 结果集转换成 List 集合。
- ParameterHandler 负责对⽤户传递的参数转换成 JDBC Statement 所需要的参数。
- SqlSource 负责根据用户传递的 parameterObject,动态地生成 SQL 语句,将信息封装到 BoundSql 对象中,并返回。
- BoundSql 表示动态生成的 SQL 语句以及相应的参数信息。
- Executor Mybatis 执行器,是 Mybatis 调度的核心,负责 SQL 语句的生成和查询缓存的维护工作。
- SqlSession 作为 Mybatis 工作的主要顶层 API,表示和数据库交互的会话,完成必要数据库增删改查功能。
- ResultSetHandler 负责将 JDBC 返回的 ResultSet 结果集对象转换成 List 类型的集合。
Mybatis 使用
// 1.初始化 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); inputStream.close(); // 2.获取sqlSession对象 SqlSession session = sqlSessionFactory.openSession(); // 3.获取dao代理对象 DspUserDao dspUserDao = session.getMapper(DspUserDao.class); // 4.执行sql DspUser user = dspUserDao.selectUserByName("test"); System.out.println(user.getUserName());
源码分析
配置文件初始化流程
1. SqlSessionFactoryBuilder
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactoryBuilder 为⼊口点进行传⼊解析 xml。
2. XMLConfigBuilder
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); build(parser.parse());
将 XML 进⾏节点解析,封装为 configuration 对象。
private void parseConfiguration(XNode root) { try { // 解析properties this.propertiesElement(root.evalNode("properties")); // 解析settings,设置默认值 Properties settings = this.settingsAsProperties(root.evalNode("settings")); this.loadCustomVfs(settings); // 解析typeAliases,设置别名 this.typeAliasesElement(root.evalNode("typeAliases")); // plugins,设置拦截器链 this.pluginElement(root.evalNode("plugins")); this.objectFactoryElement(root.evalNode("objectFactory")); this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); this.reflectorFactoryElement(root.evalNode("reflectorFactory")); this.settingsElement(settings); // environments,设置数据源,tx相关信息 this.environmentsElement(root.evalNode("environments")); this.databaseIdProviderElement(root.evalNode("databaseIdProvider")); // 解析typeHandlers,类型处理类 this.typeHandlerElement(root.evalNode("typeHandlers")); // 解析mapper,处理sql相关信息 this.mapperElement(root.evalNode("mappers")); } catch (Exception var3) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " var3, var3); } }
3.sql.xml解析⼊口
public void parse() { if (!this.configuration.isResourceLoaded(this.resource)) { this.configurationElement(this.parser.evalNode("/mapper"));//Map<String, MappedStatement> mappedStatements this.configuration.addLoadedResource(this.resource); this.bindMapperForNamespace();//Map<Class<?>, MapperProxyFactory<?>> knownMappers } this.parsePendingResultMaps(); this.parsePendingCacheRefs(); this.parsePendingStatements(); }
获取 sqlSession 流程
1. DefaultSqlSessionFactory
public SqlSession openSession() { return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false); } private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; DefaultSqlSession var8; try { Environment environment = this.configuration.getEnvironment(); TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); Executor executor = this.configuration.newExecutor(tx, execType); var8 = new DefaultSqlSession(this.configuration, executor, autoCommit); } catch (Exception var12) { this.closeTransaction(tx); throw ExceptionFactory.wrapException("Error opening session. Cause: " var12, var12); } finally { ErrorContext.instance().reset(); } return var8; }
2. configuration创建executor对象
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? this.defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Object executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (this.cacheEnabled) { executor = new CachingExecutor((Executor)executor); } // 此处拦截器调用链加载 Executor executor = (Executor)this.interceptorChain.pluginAll(executor); return executor; }
获取 dao 代理理对象流程
1. DefaultSqlSession获取mapper代理理对象
public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " type " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " var5, var5); } }
2. MapperProxyFactory 创建 mapperProxy 的代理理对象
protected T newInstance(MapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); } public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); }
执行查询流程
1. mapperProxy 代理理对象调⽤用 invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 若执⾏的object类的方法,直接调⽤ if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } if (this.isDefaultMethod(method)) { return this.invokeDefaultMethod(proxy, method, args); } } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); } // 缓存中获取MapperMethod MapperMethod mapperMethod = this.cachedMapperMethod(method); return mapperMethod.execute(this.sqlSession, args); }
2. 创建 MapperMethod 执⾏操作
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) { this.command = new MapperMethod.SqlCommand(config, mapperInterface, method); this.method = new MapperMethod.MethodSignature(config, mapperInterface, method); } // 根据sql类型进⾏执行 public Object execute(SqlSession sqlSession, Object[] args){ ....省略 param = this.method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(this.command.getName(), param); ....省略 }
3. DefaultSqlSession 执⾏ select 操作
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { List var5; try { // 从configuration中获取MappedStatement对象 MappedStatement ms = this.configuration.getMappedStatement(statement); // 通过executor执行MappedStatement var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception var9) { throw ExceptionFactory.wrapException("Error querying database. Cause: " var9, var9); } finally { ErrorContext.instance().reset(); } return var5; }
4. Executor
baseExecutor类
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { // 获取动态⽣成的SQL语句以及相应的参数信息 BoundSql boundSql = ms.getBoundSql(parameter); // 缓存当前查询 CacheKey key = this.createCacheKey(ms, parameter, rowBounds, boundSql); return this.query(ms, parameter, rowBounds, resultHandler, key, boundSql); } private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ....省略 // simpleExecutor执⾏查询 list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql); ....省略 }
simpleExecutor类
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; List var9; try { Configuration configuration = ms.getConfiguration(); // 创建PreparedStatementHandler预编译处理类,包含parameterHandler和resultSetHandler StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // 设置参数信息 stmt = this.prepareStatement(handler, ms.getStatementLog()); // 执⾏行行sql,并处理理结果集 var9 = handler.query(stmt, resultHandler); } finally { this.closeStatement(stmt); } return var9; }
5.创建StatementHandler
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 创建PreparedStatementHandler预编译处理类,包含parameterHandler和resultSetHandler StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); StatementHandler statementHandler = (StatementHandler)this.interceptorChain.pluginAll(statementHandler); return statementHandler; }
6.parameterHandler设置参数信息
public void parameterize(Statement statement) throws SQLException { this.parameterHandler.setParameters((PreparedStatement)statement); }
7. PreparedStatementHandler执行sql,并处理结果集
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement)statement; ps.execute(); return this.resultSetHandler.handleResultSets(ps); }
总结
本文出至:学新通技术网
标签: