ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MyBatis常用对象SqlSessionFactory和SqlSession介绍和运用

2021-05-29 23:06:18  阅读:204  来源: 互联网

标签:SqlSessionFactory String lt mybatis SqlSession gt MyBatis


前言:

学习框架一个比较好的路径阅读源码.本文介绍的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实例,通过这个实例对数据库进行操作

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

并且如果想按照上述方式得到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”/>

<span class="hljs-comment">&lt;!-- 设置类型别名 --&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-title">typeAliases</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-title">typeAlias</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"cn.itcast.javaee.mybatis.app04.Student"</span> <span class="hljs-attribute">alias</span>=<span class="hljs-value">"student"</span>/&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-title">typeAliases</span>&gt;</span>  

<span class="hljs-comment">&lt;!-- 设置一个默认的连接环境信息 --&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-title">environments</span> <span class="hljs-attribute">default</span>=<span class="hljs-value">"mysql_developer"</span>&gt;</span>  

    <span class="hljs-comment">&lt;!-- 连接环境信息,取一个任意唯一的名字 --&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-title">environment</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"mysql_developer"</span>&gt;</span>  
        <span class="hljs-comment">&lt;!-- mybatis使用jdbc事务管理方式 --&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-title">transactionManager</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"jdbc"</span>/&gt;</span>  
        <span class="hljs-comment">&lt;!-- mybatis使用连接池方式来获取连接 --&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-title">dataSource</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"pooled"</span>&gt;</span>  
            <span class="hljs-comment">&lt;!-- 配置与数据库交互的4个必要属性 --&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"driver"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${mysql.driver}"</span>/&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"url"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${mysql.url}"</span>/&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"username"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${mysql.username}"</span>/&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"password"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${mysql.password}"</span>/&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-title">dataSource</span>&gt;</span>  
    <span class="hljs-tag">&lt;/<span class="hljs-title">environment</span>&gt;</span>  

    <span class="hljs-comment">&lt;!-- 连接环境信息,取一个任意唯一的名字 --&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-title">environment</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"oracle_developer"</span>&gt;</span>  
        <span class="hljs-comment">&lt;!-- mybatis使用jdbc事务管理方式 --&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-title">transactionManager</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"jdbc"</span>/&gt;</span>  
        <span class="hljs-comment">&lt;!-- mybatis使用连接池方式来获取连接 --&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-title">dataSource</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"pooled"</span>&gt;</span>  
            <span class="hljs-comment">&lt;!-- 配置与数据库交互的4个必要属性 --&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"driver"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${oracle.driver}"</span>/&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"url"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${oracle.url}"</span>/&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"username"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${oracle.username}"</span>/&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"password"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${oracle.password}"</span>/&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-title">dataSource</span>&gt;</span>  
    <span class="hljs-tag">&lt;/<span class="hljs-title">environment</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-title">environments</span>&gt;</span>  

<span class="hljs-comment">&lt;!-- 加载映射文件--&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-title">mappers</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-title">mapper</span> <span class="hljs-attribute">resource</span>=<span class="hljs-value">"cn/itcast/javaee/mybatis/app14/StudentMapper.xml"</span>/&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-title">mappers</span>&gt;</span>  

</configuration>

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

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

 
 
  • 1
  • 2

如果是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>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

关于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<span class="hljs-preprocessor">.xml</span>文件
        InputStream resourceAsStream = Resources<span class="hljs-preprocessor">.getResourceAsStream</span>(<span class="hljs-string">"mybatis-config.xml"</span>)<span class="hljs-comment">;</span>
        //初始化mybatis,创建SqlSessionFactory类的实例
        SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder()<span class="hljs-preprocessor">.build</span>(resourceAsStream)<span class="hljs-comment">;</span>
        //创建session实例
        SqlSession session = sqlSessionFactory<span class="hljs-preprocessor">.openSession</span>()<span class="hljs-comment">;</span>
        <span class="hljs-comment">/*
         * 接下来在这里做很多事情,到目前为止,目的已经达到得到了SqlSession对象.通过调用SqlSession里面的方法,
         * 可以测试MyBatis和Dao层接口方法之间的正确性,当然也可以做别的很多事情,在这里就不列举了
         */</span>
        //插入数据
        User user = new User()<span class="hljs-comment">;</span>
        user<span class="hljs-preprocessor">.setC</span>_password(<span class="hljs-string">"123"</span>)<span class="hljs-comment">;</span>
        user<span class="hljs-preprocessor">.setC</span>_username(<span class="hljs-string">"123"</span>)<span class="hljs-comment">;</span>
        user<span class="hljs-preprocessor">.setC</span>_salt(<span class="hljs-string">"123"</span>)<span class="hljs-comment">;</span>
        //第一个参数为方法的完全限定名:位置信息+映射文件当中的id
        session<span class="hljs-preprocessor">.insert</span>(<span class="hljs-string">"com.cn.dao.UserMapping.insertUserInformation"</span>, user)<span class="hljs-comment">;</span>
        //提交事务
        session<span class="hljs-preprocessor">.commit</span>()<span class="hljs-comment">;</span>
        //关闭session
        session<span class="hljs-preprocessor">.close</span>()<span class="hljs-comment">;</span>
    } catch (IOException e) {
        e<span class="hljs-preprocessor">.printStackTrace</span>()<span class="hljs-comment">;</span>
    }
}

}

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

这里写图片描述

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

第一步首先SqlSessionFactoryBuilder去读取mybatis的配置文件,然后build一个DefaultSqlSessionFactory,即得到SqlSessionFactory

 
 
  • 1
//源码中涉及的包和具体方法为:
//涉及的包为: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对象了。

 
 
  • 1
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使用了连接池。关于数据库连接池的知识点,可以自行百度,在这里就不扩展介绍了.

      标签:SqlSessionFactory,String,lt,mybatis,SqlSession,gt,MyBatis
      来源: https://blog.csdn.net/Linwang2020/article/details/117392440

      本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
      2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
      3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
      4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
      5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

      专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

      Copyright (C)ICode9.com, All Rights Reserved.

      ICode9版权所有