本文讨论 Spring 与 MyBatis 的整合。

在 beans.xml 中我们定义了两个 bean: SqlSessionFactoryBean、SqlSessionTemplate。

1、SqlSessionFactoryBean

a、SqlSessionFactoryBean 是 FactoryBean,它在 Spring 容器中通过 getObject() (单例模式)返回 SqlSessionFactory bean。源码如下:

   public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
} return this.sqlSessionFactory;
}

可以看出,SqlSessionFactoryBean 对 sqlSessionFactory 是懒加载。

b、afterPropertiesSet() 源码如下:

   public void afterPropertiesSet() throws Exception {
notNull(dataSource, "Property 'dataSource' is required");
notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required"); this.sqlSessionFactory = buildSqlSessionFactory();
}

afterPropertiesSet() 先检查 dataSource、sqlSessionFactoryBuilder 是否为 null。

dataSource 在 beans.xml 中设置,sqlSessionFactoryBuilder 在新建 sqlSessionFactoryBean 时会自动创建。

c、protected SqlSessionFactory buildSqlSessionFactory() throws Exception;

这个方法设置了 transactionFactory (默认为 SpringManagedTransactionFactory),生成 environment,放入 configuration 中。

然后对 mapperLocations(Resource[]) 进行解析,放入 configuration 的 mappedStatements 中。

最后调用 sqlSessionBuilder.build(configuration) 返回 sqlSessionFactory。

d、在 beans.xml 中给 SqlSessionFactoryBean 设置了 dataSource、mapperLocations 两个参数。

2、SqlSessionTemplate 构造方法接收一个 SqlSessionFactory 参数,最终会调用以下的构造方法:

 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
}

sqlSessionFactory 默认 executorType 为 Simple,exceptionTranslator 为 MyBatisExceptionTranslator。

SqlSessionTemplate 可以加入到 Spring 的事务中,且线程安全,而 DefaultSqlSession 没有这两个特性。

3、DAO 层对数据库的访问最后都被 SqlSessionInterceptor 拦截。

这里用到了 JDK 反射功能。

private class SqlSessionInterceptor implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 获取sqlSession,其中包含了statement id
final SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
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) {
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
// 关闭session
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}

可以看出,对 sqlSession 的获取和关闭、事务管理、异常管理都由这个内部类 SqlSessionInterceptor 负责;业务层只需专注 SQL 的编写,无需再关注对资源、事务及异常的管理。

代理的目的是加入透明的对资源、事务、异常的管理。

最终委托给 DefaultSqlSession 去访问数据库:从 configuration 获取 MappedStatement,由 Executor(默认 CachingExecutor)完成对 DB 的访问。

Spring 与 MyBatis 的整合的更多相关文章

  1. 关于Spring和mybatis的整合

    Spring同Mybatis的整合 1.引入相应的jar包.(Mybatis的jar包,Spring的jar包,mybatis-spring-1.1.1.jar). 2.编写相应的包(三层的包).搭建 ...

  2. 基于maven进行spring 和mybatis的整合(Myeclpise)

    学习日记:基于maven进行spring和mybatis的整合,进行分页查询 什么是maven:maven是一个项目管理工具,使用maven可以自动管理java项目的整个生命周期,包括编译.构建.测试 ...

  3. Spring+SpringMVC+MyBatis+easyUI整合基础篇(六)maven整合SSM

    写在前面的话   承接前文<Spring+SpringMVC+MyBatis+easyUI整合基础篇(五)讲一下maven>,本篇所讲述的是如何使用maven与原ssm项目整合,使得一个普 ...

  4. Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复

    写在前面的话 在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录.本文就是写一下发现问题的过程及解决方法.此bug在第一个项目中点这里还存在, ...

  5. Spring+SpringMVC+MyBatis+easyUI整合基础篇(十一)SVN服务器进阶

    日常啰嗦 上一篇文章<Spring+SpringMVC+MyBatis+easyUI整合基础篇(十)SVN搭建>简单的讲了一下SVN服务器的搭建,并没有详细的介绍配置文件及一些复杂的功能, ...

  6. Spring+SpringMVC+MyBatis+easyUI整合基础篇(十二)阶段总结

    不知不觉,已经到了基础篇的收尾阶段了,看着前面的十几篇文章,真的有点不敢相信,自己竟然真的坚持了下来,虽然过程中也有过懒散和焦虑,不过结果还是自己所希望的,克服了很多的问题,将自己的作品展现出来,也发 ...

  7. Spring+SpringMVC+MyBatis+easyUI整合优化篇(二)Log4j讲解与整合

    日常啰嗦 上一篇文章主要讲述了一下syso和Log间的一些区别与比较,重点是在项目的日志功能上,因此,承接前文<Spring+SpringMVC+MyBatis+easyUI整合优化篇(一)Sy ...

  8. Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例

    日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(三)代码测试>讲了不为和不能两个状态,针对不为,只能自己调整心态了,而对于不能,本文会结合一 ...

  9. Spring+SpringMVC+MyBatis+easyUI整合优化篇(五)结合MockMvc进行服务端的单元测试

    日常啰嗦 承接前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例>,已经讲解了dao层和service层的单元测试,还有控制器这层也不能 ...

  10. Spring+SpringMVC+MyBatis+easyUI整合优化篇(七)图片上传功能

    日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合>讲了富文本编辑器UEditor的整合与使用 ...

随机推荐

  1. Prometheus Monitoring System & Time Series Database

    什么是 TSDB (Time Series Database): 我们可以简单的理解为.一个优化后用来处理时间序列数据的软件,并且数据中的数组是由时间进行索引的. 时间序列数据库的特点: 大部分时间都 ...

  2. tomcat 日志禁用

    1.禁用catalina.out日志通过修改catalina.sh配置可以控制tomcat不生成该文件只要将if [ -z "$CATALINA_OUT" ] ; then CAT ...

  3. TCP的三个接收队列

    之前对于TCP接收过程中的三个队列的关系之前没搞清楚. 这几天,在同事邱的帮助下,终于把关系理清了,故特此做个笔记. 一.在软中断中加入数据包 tcp_v4_rcv()函数是tcp层收包的入口. in ...

  4. 使用Jenkins进行持续集成

    首先,我们从Jenkins官方网站https://jenkins.io/下载最新的war包.虽然Jenkins提供了Windows.Linux.OS X等各种安装程序,但是,这些安装程序都没有war包 ...

  5. hdu 5236 Article(概率dp¥)

    Article Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  6. TCP/IP Socket 的理解

         网络由下往上分为:物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.      TCP 协议对应于传输层,HTTP 协议对应应用层,Socket 则是对 TCP/IP 协议的封装. ...

  7. 伯乐在线资讯URL

    伯乐资讯URL # encoding: utf-8 import requests from bs4 import BeautifulSoup import csv import time base_ ...

  8. 关于调接口和腾讯云cos方面。

    腾讯云的cos js jdk那个文档使用说明不好用. 都没看懂,而且图片上传也没有具体的详细.对于新手来说强制使用这个,弄得自己一头雾水. 工作效率就会下降. 为此我在网上搜了对象存储cos的常见错误 ...

  9. android Application Project目录结构

    src:存放java源文件 gen: 资源配置文件 Android4.0: 4.0 类库 Android Private Lib: 支持库 Android Dependencies: android ...

  10. java学习笔记 --- 多线程(线程安全问题——同步代码块)

    1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...