学习框架一个比较好的路径阅读源码.本文介绍的SqlSessionFactory和SqlSession.可以通过了解SqlSessionFactory接口和SqlSession接口以及两个的实现类入手,去看源码了解实现过程.最好能把项目下载到本地,慢慢分析实现过程.

Myabtis官网:http://www.mybatis.org/ 
github地址:https://github.com/mybatis/mybatis-3

MyBatis的持久化解决方案是将用户从原始的JDBC访问中解放出来,用户只需要定义需要操作的SQL语句,无须关注底层的JDBC操作,就可以以面向对象的方式来进行持久化层操作.底层数据库连接的获取,数据访问的实现,事务控制等都无须用户关心,从而将应用层从底层的JDBC/JTA API抽取出来.通过配置文件管理JDBC连接,让MyBatis解决持久化的实现.在MyBatis中的常见对象有SqlSessionFactory和SqlSession.本文这种介绍一下两者的概念和使用.


一、 SqlSessionFactory

SqlSessionFactory是MyBatis的关键对象,它是个单个数据库映射关系经过编译后的内存镜像.SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象类获得,而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例.每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心.同时SqlSessionFactory也是线程安全的,SqlSessionFactory一旦被创建,应该在应用执行期间都存在.在应用运行期间不要重复创建多次,建议使用单例模式.SqlSessionFactory是创建SqlSession的工厂.

//SqlSessionFactory接口源码如下所示:

package org.apache.ibatis.session;

import java.sql.Connection;

public interface SqlSessionFactory {

  SqlSession openSession();//这个方法最经常用,用来创建SqlSession对象.

  SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection); Configuration getConfiguration(); }

二、SqlSession

SqlSession是MyBatis的关键对象,是执行持久化操作的独享,类似于JDBC中的Connection.它是应用程序与持久层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象.SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句.每个线程都应该有它自己的SqlSession实例.SqlSession的实例不能被共享,同时SqlSession也是线程不安全的,绝对不能讲SqlSeesion实例的引用放在一个类的静态字段甚至是实例字段中.也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Servlet当中的HttpSession对象中.使用完SqlSeesion之后关闭Session很重要,应该确保使用finally块来关闭它.

//SqlSession接口源码如下所示:

package org.apache.ibatis.session;

import java.io.Closeable;
import java.sql.Connection;
import java.util.List;
import java.util.Map; import org.apache.ibatis.executor.BatchResult; public interface SqlSession extends Closeable { <T> T selectOne(String statement); <T> T selectOne(String statement, Object parameter); <E> List<E> selectList(String statement); <E> List<E> selectList(String statement, Object parameter); <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds); <K, V> Map<K, V> selectMap(String statement, String mapKey); <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey); <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds); void select(String statement, Object parameter, ResultHandler handler); void select(String statement, ResultHandler handler); void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler); int insert(String statement); int insert(String statement, Object parameter); int update(String statement); int update(String statement, Object parameter); int delete(String statement); int delete(String statement, Object parameter); void commit(); void commit(boolean force); void rollback(); void rollback(boolean force); List<BatchResult> flushStatements(); void close(); void clearCache(); Configuration getConfiguration(); <T> T getMapper(Class<T> type); Connection getConnection();
}

三、SqlSessionFactory和SqlSession实现过程

mybatis框架主要是围绕着SqlSessionFactory进行的,创建过程大概如下:

(1)、定义一个Configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性设置settings

(2)、通过配置对象,则可以创建一个SqlSessionFactoryBuilder对象

(3)、通过 SqlSessionFactoryBuilder 获得SqlSessionFactory 的实例。

(4)、SqlSessionFactory 的实例可以获得操作数据的SqlSession实例,通过这个实例对数据库进行操作

并且如果想按照上述方式得到SqlSessionFactory,最好使用下面的mybatis-config.xml类似的配置.在这里mybatis-config.xml配置文件是没有和Spring配置文件整合过得,如果项目中mybaits的配置文件和Spring配置文件整合过了,则下面的代码运行估计会出错,因为一般spring和mybatis整合过之后,mybatis的配置文件基本没有存在的必要了,之前在mybatis中配置的数据源和事务这两个方面,一般的做法都会spring的配置文件,则下面的代码加载mybatis-config.xml的时候,得不到必要的信息,创建的过程中会有问题.所以在这里先给一份mybatis-config.xml单独的配置文件.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<!-- 加载类路径下的属性文件 -->
<properties resource="db.properties"/> <!-- 设置类型别名 -->
<typeAliases>
<typeAlias type="cn.itcast.javaee.mybatis.app04.Student" alias="student"/>
</typeAliases> <!-- 设置一个默认的连接环境信息 -->
<environments default="mysql_developer"> <!-- 连接环境信息,取一个任意唯一的名字 -->
<environment id="mysql_developer">
<!-- mybatis使用jdbc事务管理方式 -->
<transactionManager type="jdbc"/>
<!-- mybatis使用连接池方式来获取连接 -->
<dataSource type="pooled">
<!-- 配置与数据库交互的4个必要属性 -->
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment> <!-- 连接环境信息,取一个任意唯一的名字 -->
<environment id="oracle_developer">
<!-- mybatis使用jdbc事务管理方式 -->
<transactionManager type="jdbc"/>
<!-- mybatis使用连接池方式来获取连接 -->
<dataSource type="pooled">
<!-- 配置与数据库交互的4个必要属性 -->
<property name="driver" value="${oracle.driver}"/>
<property name="url" value="${oracle.url}"/>
<property name="username" value="${oracle.username}"/>
<property name="password" value="${oracle.password}"/>
</dataSource>
</environment>
</environments> <!-- 加载映射文件-->
<mappers>
<mapper resource="cn/itcast/javaee/mybatis/app14/StudentMapper.xml"/>
</mappers> </configuration>

下面的这行代码功能是通过配置文件mybatis-config.xml,创建SqlSessionFactory对象,然后产生SqlSession,执行SQL语句.而mybatis的初始化发生在:

SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder().build(resourceAsStream);

如果是spring和mybaits整合之后的配置文件,一般以这种方式实现,SqlSessionFactory的创建:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:com/cn/mapper/*.xml"></property>
</bean>

关于SqlSessionFactory和SqlSession两个对象给一个具体的使用过程:

package com.cn.testIUserService;

import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.cn.entity.User; public class MyBatisTest { public static void main(String[] args) {
try {
//读取mybatis-config.xml文件
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
//初始化mybatis,创建SqlSessionFactory类的实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建session实例
SqlSession session = sqlSessionFactory.openSession();
/*
* 接下来在这里做很多事情,到目前为止,目的已经达到得到了SqlSession对象.通过调用SqlSession里面的方法,
* 可以测试MyBatis和Dao层接口方法之间的正确性,当然也可以做别的很多事情,在这里就不列举了
*/
//插入数据
User user = new User();
user.setC_password("123");
user.setC_username("123");
user.setC_salt("123");
//第一个参数为方法的完全限定名:位置信息+映射文件当中的id
session.insert("com.cn.dao.UserMapping.insertUserInformation", user);
//提交事务
session.commit();
//关闭session
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

针对上面的代码给出详细的说明关于SqlSessionFactory和SqlSession创建过程涉及的内容.

结合上述SqlSessionFactory和SqlSession使用过程和结构图,涉及到的方法为下面步骤,结合源码中的方法为下面的步骤:

第一步首先SqlSessionFactoryBuilder去读取mybatis的配置文件,然后build一个DefaultSqlSessionFactory,即得到SqlSessionFactory
//源码中涉及的包和具体方法为:
//涉及的包为:package org.apache.ibatis.session; //第一个类为:SqlSessionFactoryBuilder,设计到此类的方法为下面部分:
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
} public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
//通过XMLConfigBuilder解析配置文件,解析的配置相关信息都会封装为一个Configuration对象
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//然后返回一个DefaultSqlSessionFactory
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
} //得到DefaultSqlSessionFactory
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
} //第二个类为:DefaultSqlSessionFactory,涉及的方法为:
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
第二步,获取到SqlSessionFactory之后,就可以利用SqlSessionFactory方法的openSession来获取SqlSession对象了。
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//通过Confuguration对象去获取Mybatis相关配置信息, Environment对象包含了数据源和事务的配置
// execType为执行器类型,配置文件中定义
// SimpleExecutor -- SIMPLE 就是普通的执行器。
//ReuseExecutor -执行器会重用预处理语句(prepared statements)
//BatchExecutor --它是批量执行器
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//定义执行器,是对statement的封装
final Executor executor = configuration.newExecutor(tx, execType);
//最后返回一个SqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}

得到SqlSession对象之后就可以利用SqlSession内部的方法进行CRUD操作了。

注意一点,Connection对象是在SqlSession对象创建之后进行CURD操作中创建的。深入查找之后找到在ManagedTransaction类中找到获取Connection对象的关键代码如下:

  protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Opening JDBC Connection");
}
//dataSource 来源有三种,JndiDatasource,PooledDataSource,UnpooledDataSource,配置文件中定义
this.connection = this.dataSource.getConnection();
if (this.level != null) {
this.connection.setTransactionIsolation(this.level.getLevel());
}
}

PooledDataSource和UnPooledDataSource的区别是PooledDataSource使用了连接池。为什么使用连接池呢?因为创建一个Connection对象的过程,在底层就相当于和数据库建立的通信连接,在建立通信连接的过程,消耗了非常多的时间,而往往我们建立连接后(即创建Connection对象后),就执行一个简单的SQL语句,然后就要抛弃掉,这是一个非常大的资源浪费!mybatis针对这一个问题提出的PooledDataSource使用了连接池。关于数据库连接池的知识点,可以自行百度,在这里就不扩展介绍了.

MyBatis常用对象SqlSessionFactory和SqlSession介绍和运用的更多相关文章

  1. Mybatis学习(二)常用对象SqlSessionFactory和SqlSession

    1.SqlSessionFactory SqlSeesionFactory对象是MyBatis的关键对象,它是一个数据库映射关系经过编译后的内存镜像. SqlSeesionFactory对象的实例可以 ...

  2. mybatis的两个核心对象SqlSessionFactory和SqlSession对象

    mybatis的两个核心对象SqlSessionFactory和SqlSession对象 参见:https://www.cnblogs.com/wxdestiny/p/9743686.html

  3. (五)myBatis架构以及SQlSessionFactory,SqlSession,通过代理执行crud源码分析---待更

    MyBatis架构 首先MyBatis大致上可以分为四层: 1.接口层:这个比较容易理解,就是指MyBatis暴露给我们的各种方法,配置,可以理解为你import进来的各种类.,告诉用户你可以干什么 ...

  4. Mybatis之:SqlSessionFactory、SqlSession

    public class CountryMapperTest { private static SqlSessionFactory sqlSessionFactory; @BeforeClass pu ...

  5. Mybatis中SqlSessionFactory和SqlSession学习和原理

    源码git地址:https://github.com/mybatis/mybatis-3 目标结构: mybatis是数据持久化解决方案将用户从JDBC访问中解放出来,用户只需要定义需要操作的SQL语 ...

  6. MyBatis的2个核心对象:SqlSessionFactory、SqlSession

    SqlSessionFactory SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession. InputStream inputStream = ...

  7. Mybatis-学习笔记(1)SqlSessionFactory、SqlSession、Mybatis配置文件configuration的属性标签

    1.mybatis引入项目,只需要引入mybatis-x.x.x.jar包即可. (当然数据库驱动的引入必不可少) 2.SqlSessionFactory 由SqlSessionFactoryBuil ...

  8. 关于Mybatis与Spring整合之后SqlSession与mapper对象之间数量的问题。

    1,sqlsession的真实类型和数量 由于使用spring管理bean,当我们在代码中需要使用这个bean的时候,会首先去容器中找,第一次需要调用MapperFactoryBean的getObje ...

  9. mybatis源码阅读-SqlSessionFactory和SqlSession(三)

    说明 读了3遍:https://my.oschina.net/zudajun/blog/665956 现在统一整理成笔记 并跟着源码一行一行调试 统一整理起来 SqlSession 接口定义 publ ...

随机推荐

  1. git fatal: https://github.com/TeaCodie/TeaCodie-Website.git/info/refs not found: did you run git update-server-info on the server 错误

    错误: fatal: https://github.com/TeaCodie/TeaCodie-Website.git/info/refs not found: did you run git upd ...

  2. 取石子(六)_nyoj_585(博弈-奇异矩阵).java

    取石子(六) 时间限制: 1000 ms  |  内存限制: 65535 KB 难度: 3   描述 最近 TopCoder 的 PIAOYI 和 HRDV 很无聊,于是就想了一个游戏,游戏是这样的: ...

  3. JavaScript操作符

    一元操作符 只能操作一个值的操作符叫做一元操作符. 递增和递减操作符 递增和递减操作符遵循下列规则:         在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减 1 的操作 ...

  4. Android API之android.os.AsyncTask

    android.os.AsyncTask<Params, Progress, Result> AsyncTask enables proper and easy use of the UI ...

  5. cocos2d-html5学习笔记(六)--alpha2中cc.Sequence.create中的bug

    cocos2d-html5学习笔记(六)--alpha2中cc.Sequence.create中的bug http://blog.csdn.net/allenice1/article/details/ ...

  6. unity3D中使用Socket进行数据通信(二)

    上一篇博客主要介绍了使用socket搭建服务端和client程序,这一篇来说说socket的数据传输,我们使用socket的目的是解决点对点之间的数据传输,之前提到了socket中一个重要的概念:po ...

  7. fatfs文件系统f_lseek追加文件

    http://home.eeworld.com.cn/my/space-uid-430378-blogid-74720.html 这个时候我以为读出的数据应该是stm32f107学习!!!文件系统学习 ...

  8. B/S打印解决方案参考

    使用Lodop 插件,该插件占用8000端口,未使用过,仅知依赖浏览器打印 http://blog.csdn.net/harderxin/article/details/17262945 强大的web ...

  9. Jquery 大纲

    1,核心 核心函数 对象訪问 数据缓存 队列控制 插件机制 多库共存 2.选择器 基本选择器 层级 基本 内容 可见性 属性 子元素 表单 表单对象属性 3.文档处理 内部插入 外部插入 包裹 替换 ...

  10. QT实现右键快捷菜单

    [转自]:http://blog.csdn.net/rolland1989/article/details/5754575 QWidget及其子类都可有右键菜单,因为QWidget有以下两个与右键菜单 ...