Mybatis的SqlSession理解(二)
Mybaits加载执行该xml配置

class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean
spring 在初始化 sqlsessionbean的时候通过createBean调用了在SqlSessionFactoryBean中实现了接口InitializingBean的afterPropertiesSet()方法在该方法中调用了buildSqlSessionFactory()开始创建SqlSessionFactory
buildSqlSessionFactory()方法完成以下功能
一:
a) 创建configuration
b) typeAliasesPackage
c) typeAliases TYPE_ALIASES将类型存放到此map里面同b
d) plugins configuration添加插件
e) typeHandlersPackage
f) typeHandlers
g) xmlConfigBuilder.parse()将所有的配置从xml中读取并放入到对应的变量里面
h) mapperLocations
二:xmlMapperBuilder.parse()——> configurationElement
a) parameterMapElement(context.evalNodes("/mapper/parameterMap"));将mapper.xml中的prameterMap节点的数据添加到configuration.parameterMaps中
b) resultMapElements(context.evalNodes("/mapper/resultMap"));将mapper.xml中的resultMap节点的数据添加到configuration.incompleteResultMaps中
c) sqlElement(context.evalNodes("/mapper/sql"));
d) buildStatementFromContext(select|insert|update|delete);buildStatementFromContext:从mapper 中获取sql语句,执行类型(增删改查),parseStatementNode中addMappedStatement创建每个mapper对应的方法创建MappedStatement并添加到 configuration.mappedStatements.put(com.qb.mysql.dao.TRoleDao.getUserRoleByRid, MappedStatement)
最后返回了一个 DefaultSqlSessionFactory(config)
在调用SqlSessionTemplate进行dao层操作时,其会将工作委托给sqlSessionProxy属性进行,而sqlSessionProxy在进行相关method调用时,用到了JDK动态代理机制,首先SqlSessionUtils.getSqlSession获取sqlSession
private class SqlSessionInterceptor implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//返回一个DefaultSqlsession
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
//调用该类的MapperProxy的invoke方法
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
在getSqlSession方法中创建事务,创建Executor,默认创建SimpleExecutor;InterceptorChain添加拦截器 InterceptorChain.pluginAll()
SqlSessionTemplate ->SqlSessionInterceptor->SqlSessionUtils. getSqlSession()->(defaultsqlsessionfactory)sessionFactory.openSession()->openSessionFromDataSource()
MapperProxy的invoke方法的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
//执行execute
return mapperMethod.execute(sqlSession, args);
}
//根据sql类型选择对应的方法
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
if (SqlCommandType.INSERT == command.getType()) {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
} else if (SqlCommandType.UPDATE == command.getType()) {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
} else if (SqlCommandType.DELETE == command.getType()) {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
} else if (SqlCommandType.SELECT == command.getType()) {
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
}
} else {
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
SqlSessionTemplate 执行了创建sqlsession,openSqlsession,执行sql,closeSqlsession
Mybatis的SqlSession理解(二)的更多相关文章
- Mybatis的SqlSession理解(一)
SqlSession是Mybatis最重要的构建之一,可以认为Mybatis一系列的配置目的是生成类似JDBC生成的Connection对象的statement对象,这样才能与数据库开启“沟通”,通过 ...
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- Java数据持久层框架 MyBatis之背景知识二
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- MyBatis基础入门《二》Select查询
MyBatis基础入门<二>Select查询 使用MySQL数据库,创建表: SET NAMES utf8mb4; ; -- ---------------------------- -- ...
- mybatis 学习笔记(二):mybatis SQL注入问题
mybatis 学习笔记(二):mybatis SQL注入问题 SQL 注入攻击 首先了解下概念,什么叫SQL 注入: SQL注入攻击,简称SQL攻击或注入攻击,是发生于应用程序之数据库层的安全漏洞. ...
- (转)MyBatis框架的学习(二)——MyBatis架构与入门
http://blog.csdn.net/yerenyuan_pku/article/details/71699515 MyBatis框架的架构 MyBatis框架的架构如下图: 下面作简要概述: S ...
- 用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建二:配置MyBatis 并测试(2 配置spring-dao和测试)
用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建二:配置MyBatis 并测试(1 搭建目录环境和依赖) 四:在\resources\spring 下面 ...
- 用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建二:配置MyBatis 并测试(1 构建目录环境和依赖)
引言:在用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建一 的基础上 继续进行项目搭建 该部分的主要目的是测通MyBatis 及Spring-dao ...
- Springboot & Mybatis 构建restful 服务二
Springboot & Mybatis 构建restful 服务二 1 前置条件 成功执行完Springboot & Mybatis 构建restful 服务一 2 restful ...
随机推荐
- use right spindle drive
Hardware software interface: HallSupplyLeft: E_BSW_DO_SUP_HCOM_A Left Hall Sensor: E_BSW_DI_HALL_A_1 ...
- 基于SecureCRT的测试环境的克隆的linux/vi相关命令
#chmod -R 777*; 参数-R:对当前目录下的所有档案与子目录进行相同的权限 变更(即以递归的方式逐个变更). *:通配符,指的是当前目录下的所有文件及目录. 所有文件及其子目录的文件拥有者 ...
- Fiddler抓取指定域名
有时候我们抓取app软件的包时,其他很多软件进程的请求会造成干扰 这时我们就需要过滤只抓取我们需要域名的包 切换到Fiddler右侧窗口的Filters选项卡,勾选顶部的Use Filters,找到H ...
- 通过经纬度获取所属城市信息-php
测试经纬度信息,37.863036,113.598909.通过地图查询,所在城市为:阳泉. <?php class test{ public static $test_key = 'dfgfdg ...
- Python 2、8、10、16进制间的转换
进制转换一直是初学者所头疼的,下面就简单的列出各进制之间都是以什么方式转换的. # print('2-->8: ', oct(int('0b1010', 2))) # 2-10-8 # prin ...
- 鸡兔同笼问题(Java)
问题描述:编程解决鸡兔同笼问题,笼子中鸡兔共有35只,94只脚,求有鸡和兔各有几只 我的代码: /** * 鸡兔同笼问题 * @author Administrator * */ public cla ...
- JS事件覆盖问题和触发问题
昨天遇到一个面试题,主要就是事件覆盖问题和触发问题 (不是打广告,无视文本内容) 总之这样的话,会输出三次“做自己的网站”. 为什么不是两次,而是输出三次呢? 1.首先onclick=function ...
- dubbo接口FindMemberInfoTest思路整合
package com.yzb.user_center; /** * @Created by IntelliJ IDEA. * @Author tk * @Date 2018/7/31 * @Time ...
- Python3基础 list insert 在指定位置挤入一个元素
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Spring Boot 项目中常见注解
@Autowired 自动导入依赖的 Bean.byType方式.把配置好的 Bean拿来用,完成属性.方法的组装,它可以对类成员变量.方法及构造函数进行标注,完成自动装配的工作 import org ...