SqlSession

简介: SqlSession

实现类可以进行增删查改以及事务操作


利用SqlSession内部的方法进行CRUD操作


SqlSession重要的四个对象

1)Execute:调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句

2)StatementHandler:使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement;

3)ParammeterHandler:处理SQL参数;

4)ResultHandler:结果集ResultSet封装处理返回

在 MyBatis 中,真正干活的是 Executor,我们会在底层看到它

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


SqlSession接口源码如下所示:


//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();
}

那么DefaultSqlSession是怎么进行这些操作的呢?答:通过调用Executor执行器.


Executor执行器.


负责执行SQL语句,并且封装结果集


下面是Executor 的举例


package com.itheima.mybatis.utils;
import com.itheima.mybatis.cfg.Mapper;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * 负责执行SQL语句,并且封装结果集
 */
public class Executor {
    public <E> List<E> selectList(Mapper mapper, Connection conn) {
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try {
            //1.取出mapper中的数据
            String queryString = mapper.getQueryString();//select * from user
            String resultType = mapper.getResultType();//com.itheima.domain.User
            Class domainClass = Class.forName(resultType);
            //2.获取PreparedStatement对象
            pstm = conn.prepareStatement(queryString);
            //3.执行SQL语句,获取结果集
            rs = pstm.executeQuery();
            //4.封装结果集
            List<E> list = new ArrayList<E>();//定义返回值
            while(rs.next()) {
                //实例化要封装的实体类对象
                E obj = (E)domainClass.newInstance();
                //取出结果集的元信息:ResultSetMetaData
                ResultSetMetaData rsmd = rs.getMetaData();
                //取出总列数
                int columnCount = rsmd.getColumnCount();
                //遍历总列数
                for (int i = 1; i <= columnCount; i++) {
                    //获取每列的名称,列名的序号是从1开始的
                    String columnName = rsmd.getColumnName(i);
                    //根据得到列名,获取每列的值
                    Object columnValue = rs.getObject(columnName);
                    //给obj赋值:使用Java内省机制(借助PropertyDescriptor实现属性的封装)
                    PropertyDescriptor pd = new PropertyDescriptor(columnName,domainClass);//要求:实体类的属性和数据库表的列名保持一种
                    //获取它的写入方法
                    Method writeMethod = pd.getWriteMethod();
                    //把获取的列的值,给对象赋值
                    writeMethod.invoke(obj,columnValue);
                }
                //把赋好值的对象加入到集合中
                list.add(obj);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            release(pstm,rs);
        }
    }
    private void release(PreparedStatement pstm,ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        if(pstm != null){
            try {
                pstm.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

    所以,咱们平时见到的SqlSession.select()等等其实是在操作DefaultSqlSession.select()的方法,而DefaultSqlSession的方法其实也不是就能够实现对数据库进行操作的,而是通过调用Executor执行器来执行

   而Executor执行器其实也是一个接口,而在解析配置文件的时候已经解析出来SQL,那么根据一路传过来的SQL以及参数等信息,Executor再调度StatementHandler等对象对数据库进行增删查改操作.


总结:现在你应该明白了吧,其实我们看到的都是表面,你认为的SqlSession能进行数据库操作其实不是的,是它的实现类再调用底层的Executor,底层的Executor再调度相关数据库操作对象才搞定的,而再要深入它的相关对象,那么就深似海了…


   如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务。

所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try…catch…finally… 语句来保证其正确关闭。

相关文章
|
5月前
|
缓存 安全 Java
Hibernate 中的 SessionFactory 是什么?
【8月更文挑战第21天】
73 0
|
Java 数据库连接 数据库
【MyBatis】sqlSession.getMapper详解
【MyBatis】sqlSession.getMapper详解
241 0
|
8月前
|
缓存 Java 数据库连接
一文彻底搞懂Mybatis系列(十)之SqlSession、SqlSessionFactory和SqlSessionFactoryBuilder详解
一文彻底搞懂Mybatis系列(十)之SqlSession、SqlSessionFactory和SqlSessionFactoryBuilder详解
1120 1
|
8月前
|
SQL 缓存 Java
Hibernate - SessionFactory和Session详解
Hibernate - SessionFactory和Session详解
161 0
|
XML SQL 设计模式
|
XML SQL Java
SqlSession接口|学习笔记
快速学习SqlSession接口
SqlSession接口|学习笔记
|
SQL 安全 Java
MyBatis——通过占位符实现insert操作、一些重要对象(SqlSessionFactory、SqlSession)的理解
MyBatis——通过占位符实现insert操作、一些重要对象(SqlSessionFactory、SqlSession)的理解
MyBatis——通过占位符实现insert操作、一些重要对象(SqlSessionFactory、SqlSession)的理解
|
Java 数据库连接 mybatis
MyBatis - ThreadLocal<SqlSession>
MyBatis - ThreadLocal<SqlSession>
268 0
MyBatis - ThreadLocal<SqlSession>
|
SQL Java 数据库连接
MyBatis - SqlSession(下)
MyBatis - SqlSession(下)
157 0