精华内容
下载资源
问答
  • 这回是学习一下SqlSession中一些相关的作用域和生命周期 作用域和生命周期 生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。一个mybatis的执行流程如下图所示。 SqlSessionFactoryBuilder...

    这回是学习一下SqlSession中一些相关的作用域和生命周期

    作用域和生命周期

    生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。一个mybatis的执行流程如下图所示。

    在这里插入图片描述

    SqlSessionFactoryBuilder:

    • 一旦创建了SqlSessionFactory,就不需要它了。
    • 所以比较适合在局部变量中创建。

    SqlSessionFactory:

    • 相当于数据库的连接池。
    • SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
    • 所以SqlSessionFactory比较适合应用作用域,也就是全局。
    • 最简单的就是使用单例模式或者静态单例模式。

    SqlSession

    • 连接到连接池的一个请求。
    • 关闭请求。
    • 因为它不是线程安全的,不能共享。用完之后必须要关闭,否则资源被占用。
    • 因此它的作用域是请求或者方法作用域。

    在这里插入图片描述

    展开全文
  • Mybatis sqlsession解析

    2018-11-14 14:47:00
     在mybatis框架下进行的数据库操作都需要首先获取sqlsession,在mybatis与spring集成后获取sqlsession需要用到sqlsessionTemplate这个类。 首先在spring对sqlsessionTemplate进行配置,使用到的是 org.mybatis....

    一、sqlsession获取过程

    1、基础配置

      在mybatis框架下进行的数据库操作都需要首先获取sqlsession,在mybatis与spring集成后获取sqlsession需要用到sqlsessionTemplate这个类。

    首先在spring对sqlsessionTemplate进行配置,使用到的是 org.mybatis.spring.SqlSessionTemplate 这个类。

    <!-- SqlSession实例 -->
    <bean id="sessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"
            destroy-method="close">
    <!--当构造函数有多个参数时,可以使用constructor-arg标签的index属性,index属性的值从0开始,这里将sqlsessionFactory作为第一个参数传入--> 
    <constructor-arg index="0" ref="sqlSessionFactory" /> 
    </bean>
    <!-- 将数据源映射到sqlSessionFactory中 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    所以在sqlsessionTemplate的初始化过程中,首先会将sqlsessionFactory作为参数传入,sqlsessionFactory中映射了数据源信息。

    配置事务,在后来的sqlsession获取过程中会对事务进行判断

    <!--======= 事务配置 Begin ================= -->
    <!-- 事务管理器(由Spring管理MyBatis的事务) -->
    <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 关联数据源 -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
    <!--======= 事务配置 End =================== -->

    2、sqlsessionTemplate的初始化

    public class SqlSessionTemplate implements SqlSession {
        private final SqlSessionFactory sqlSessionFactory;
        private final ExecutorType executorType;
        private final SqlSession sqlSessionProxy;
        private final PersistenceExceptionTranslator exceptionTranslator;
    
        public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
            this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
        }
    
        public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
            this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
        }
    
        public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
            Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
            Assert.notNull(executorType, "Property 'executorType' is required");
            this.sqlSessionFactory = sqlSessionFactory;
            this.executorType = executorType;
            this.exceptionTranslator = exceptionTranslator;
            this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());
        }

      SqlsessionTemplate类的最开始初始化过程中,首先会通过sqlsessionFactory参数进行构造,通过Proxy.newProxyInstance()方法来创建代理类,表示创建SqlSessionFactory的代理类的实例,该代理类实现SqlSession接口,定义了方法拦截器,如果调用代理类实例中实现SqlSession接口定义的方法,该调用则被导向SqlsessionTemplate的一个内部类SqlSessionInterceptor的invoke方法,最终初始化sqlsessionProxy。

    3、sqlsession的调用过程

    由于上面两个过程中已经将sqlsessionTemplate中的sqlsessionProxy已经初始化完毕,所以在代码中可以进行调用。调用最终都会进入SqlSessionInterceptor的invoke方法。

    private class SqlSessionInterceptor implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          //获取SqlSession(这个SqlSession才是真正使用的,它不是线程安全的)
          //这个方法可以根据Spring的事物上下文来获取事物范围内的sqlSession
          final SqlSession sqlSession = SqlSessionUtils.getSqlSession(
              SqlSessionTemplate.this.sqlSessionFactory,
              SqlSessionTemplate.this.executorType,
              SqlSessionTemplate.this.exceptionTranslator);
          try {
            //调用真实SqlSession的方法
            Object result = method.invoke(sqlSession, args);
            //然后判断一下当前的sqlSession是否有配置Spring事务 如果没有自动commit
            if (!SqlSessionUtils.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 {
            //关闭sqlSession
            //它会根据当前的sqlSession是否在Spring的事务上下文当中来执行具体的关闭动作
            //如果sqlSession被Spring事务管理 则调用holder.released(); 使计数器-1
            //否则才真正的关闭sqlSession
            SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          }
        }
      }

    在上面的代码中用到两个很关键的方法:

      获取sqlsession方法:SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);

      关闭sqlsession方法:SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);

    public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {     
        //根据sqlSessionFactory从当前线程对应的资源map中获取SqlSessionHolder,当sqlSessionFactory创建了sqlSession,就会在事务管理器中添加一对映射:key为sqlSessionFactory,value为SqlSessionHolder,该类保存sqlSession及执行方式 
        SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory); 
     //如果holder不为空,且和当前事务同步 
        if (holder != null && holder.isSynchronizedWithTransaction()) { 
          //hodler保存的执行类型和获取SqlSession的执行类型不一致,就会抛出异常,也就是说在同一个事务中,执行类型不能变化,原因就是同一个事务中同一个sqlSessionFactory创建的sqlSession会被重用 
          if (holder.getExecutorType() != executorType) { 
            throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction"); 
          } 
          //增加该holder,也就是同一事务中同一个sqlSessionFactory创建的唯一sqlSession,其引用数增加,被使用的次数增加 
          holder.requested(); 
       //返回sqlSession 
          return holder.getSqlSession(); 
        } 
     //如果找不到,则根据执行类型构造一个新的sqlSession 
        SqlSession session = sessionFactory.openSession(executorType); 
     //判断同步是否激活,只要SpringTX被激活,就是true 
        if (isSynchronizationActive()) { 
       //加载环境变量,判断注册的事务管理器是否是SpringManagedTransaction,也就是Spring管理事务 
          Environment environment = sessionFactory.getConfiguration().getEnvironment(); 
          if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) { 
      //如果是,则将sqlSession加载进事务管理的本地线程缓存中 
            holder = new SqlSessionHolder(session, executorType, exceptionTranslator); 
      //以sessionFactory为key,hodler为value,加入到TransactionSynchronizationManager管理的本地缓存ThreadLocal<Map<Object, Object>> resources中 
            bindResource(sessionFactory, holder); 
      //将holder, sessionFactory的同步加入本地线程缓存中ThreadLocal<Set<TransactionSynchronization>> synchronizations 
            registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory)); 
            //设置当前holder和当前事务同步 
      holder.setSynchronizedWithTransaction(true); 
      //增加引用数 
            holder.requested(); 
          } else { 
            if (getResource(environment.getDataSource()) == null) { 
            } else { 
              throw new TransientDataAccessResourceException( 
                  "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"); 
            } 
          } 
        } else { 
        } 
        return session; 
      }
    public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) { 
     //其实下面就是判断session是否被Spring事务管理,如果管理就会得到holder  
        SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory); 
        if ((holder != null) && (holder.getSqlSession() == session)) { 
       //这里释放的作用,不是关闭,只是减少一下引用数,因为后面可能会被复用 
          holder.released(); 
        } else { 
       //如果不是被spring管理,那么就不会被Spring去关闭回收,就需要自己close 
          session.close(); 
        } 
      }

    二、mybatis的缓存

    1、一级缓存

      Mybatis的一级缓存是默认开启的,主要是通过sqlsession来实现的,每个sqlsession对象会在本地创建一个缓存(local cache),对于每次查询都会在本地缓存中进行查询,如果命中则直接返回,如果没查到则进入到数据库中进行查找。一级缓存是sqlsession级别的。

      从上面sqlsession的获取源码中可以看到,每次获取一个全新的sqlsession最终都是会保存在ThreadLocal中跟线程绑定,如果在spring中配置了事务则整个事务周期里面都共享一个sqlsession,如果没有配置事务则每次请求都是一个独立的sqlsession。每次执行完后数据库操作后,如果还在事务周期中只对sqlsession的引用次数减一,否则直接关闭sqlsession。

    一级缓存执行的时序图:

     

    小结:

    MyBatis一级缓存的生命周期和SqlSession一致。
    MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
    MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

    2、二级缓存

    在系统中如果需要使用二级缓存则直接在spring中进行配置声明即可。

    <!-- 这个配置使全局的映射器启用或禁用 缓存 -->
    <setting name="cacheEnabled" value="true" />
    <!-- 开启二级缓存开关 -->
    <cache/>

      MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
      MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
      在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis,Memcached等分布式缓存可能成本更低,安全性也更高。

     

    转载于:https://www.cnblogs.com/kma-3/p/9957740.html

    展开全文
  • 阅读文章能够收获SqlSessionFactoryBuilder,SqlSessionFactory、SqlSession相关知识 “ 建议结合mybatis 源码[1]、mybatis 官网[2]阅读, 可以下载不同版本的源码, 本文根据3.4.x解读, 不同版本源码存在细微差别 ...

    阅读文章能够收获 SqlSessionFactoryBuilderSqlSessionFactorySqlSession 相关知识

    建议结合 mybatis 源码[1]、mybatis 官网[2] 阅读, 可以下载不同版本的源码, 本文根据 3.4.x 解读, 不同版本源码存在细微差别

    为防止不必要的麻烦, 直接下载 3.4.x 版本的 mybatis 源码, 文章中测试代码是在 org.apache.ibatis.autoconstructor 目录下建立新的文件夹进行测试

    01、相关概念简介

    1.1 SqlSession

    负责执行 selectinsertupdatedelete 等命令, 同时负责获取映射器和管理事务; 其底层封装了与 JDBC 的交互, 可以说是 mybatis 最核心的接口之一

    SqlSession 非线程安全, 所以每个线程都拥有一个实例; 通俗来说来一个请求就打开一个对应的 SqlSession, 使用后进行关闭

    在我们日常项目中基本都是使用 mybatisspring 整合版, 生命周期和线程安全问题不需要考虑

    SqlSession 简单理解的话, 就是你写的 SQL, 想要请求数据库, 都得经过它调取

    1.2 SqlSessionFactory

    负责创建 SqlSession 的工厂, 一旦被创建就应该在应用运行期间一直存在, 不需要额外再进行创建

    平常项目中也是配置为 spring 中一个单例 bean

    1.3 SqlSessionFactoryBuilder

    主要是负责创建 SqlSessionFactory 的构造器类, 其中使用到了构建者设计模式; 创建 SqlSessionFactory 后就没啥子用了

    在 spring 与 mybatis 的整合项目中, 构建 SqlSessionFactory 的任务交给了 SqlSessionFactoryBean, 在这里了解即可, 核心思想和处理结果是一致的

    02、SqlSession 创建代码

    下载源码之后, 在源码项目的 test目录 下面创建自己的测试包, 然后从文章底部获取 mybatis官网链接 复制创建 SqlSession 的代码, 粘贴运行即可

    @Test
    public void buildSqlSession() throws IOException {
        // mybatis-config.xml 文件路径
        String resource = "org/apache/ibatis/autoconstructor/mybatis-config.xml";
        // 根据 mybatis io 资源包下的工具类直接获取流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 这里采用字节流构建 SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 通过 sqlSessionFactory 获取 sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        System.out.println(sqlSession);
    }
    

    下面会从 SqlSessionFactoryBuilder 、 SqlSessionFactory 、 SqlSession 按照创建关系进行解析

    03、解析 SqlSessionFactoryBuilder

    通过源码看出, build() 大部分重载方法基本围绕 ReaderInputStream 这两个对象, 真正构建会话工厂的方法为 build(Configuration config)

    public SqlSessionFactory build(Reader reader)
    public SqlSessionFactory build(Reader reader, String environment)
    public SqlSessionFactory build(Reader reader, Properties properties)
    public SqlSessionFactory build(Reader reader, String environment, Properties properties)
    public SqlSessionFactory build(InputStream inputStream)
    public SqlSessionFactory build(InputStream inputStream, String environment)
    public SqlSessionFactory build(InputStream inputStream, Properties properties)
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties)
    // 创建 SqlSessionFactory 的调用方法
    public SqlSessionFactory build(Configuration config)
    

    上面入参为 Reader 的 build() 也是通过 InputStream 创建的, 从字节流转换成了字符流

    @Test
    public void buildSelSessionByReader() throws IOException {
        final Reader reader = Resources.getResourceAsReader("org/apache/ibatis/autoconstructor/mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    }
    

    字节流转换字符流方法

    public static Reader getResourceAsReader(String resource) throws IOException {
        Reader reader;
        if (charset == null) {
            reader = new InputStreamReader(getResourceAsStream(resource));
        } else {
            reader = new InputStreamReader(getResourceAsStream(resource), charset);
        }
        return reader;
    }
    

    SqlSessionFactoryBuilder 大部分 build() 方法都是为了解析出 Configuration 对象

    具体的 Configuration 解析构建比较复杂, 会单独写篇文章说明

    解析出Configuration 对象后开始创建 SqlSessionFactory, 可以看下具体实现

    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
    }
    

    04、解析 SqlSessionFactory

    SqlSessionFactory 是一个接口并非具体的类, 其具体实现类是在 build(Configuration config) 方法中创建的 new DefaultSqlSessionFactory(config)

    在实现类的构造方法中并无实际逻辑, 只是把 config 对象赋值给了内部变量 Configuration

    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }
    

    05、解析 SqlSession

    通过 04 章节已经可以得到创建 SqlSession 的 SqlSessionFactory 对象了, 那么接下来就是要解析本篇的重头戏 SqlSession

    SqlSessionFactory 接口中声明了一系列 opensession 方法,用来返回 SqlSession 对象

    SqlSession openSession();
    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);
    

    Mybatis 框架作者 Clinton Begin 可能不太喜欢写注释, 框架里面大部分接口和类都没有发现注释

    在实现类 DefaultSqlSessionFactory 中实现了接口中定义的方法, 如下

    public SqlSession openSession() {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
    }
    

    说一下返回的 openSessionFromDataSource 方法, 重载的方法其实大致都一致, 这里挑典型说明

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
            final Environment environment = configuration.getEnvironment();
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            final Executor executor = configuration.newExecutor(tx, execType);
            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();
        }
    }
    

    5.1 参数列表

    1》执行器类型 ExecutorType

    ExecutorType 是一个执行器类型枚举, 里面有三种类型 SIMPLEBATCHREUSE, 分别对应如下执行器

    SimpleExecutor: 在每次执行完成后都会关闭 statement 对象, 为默认执行器

    BatchExecutor: 会将修改操作记录在本地,等待程序触发或有下一次查询时才批量执行修改操作

    ReuseExecutor: 会在本地维护一个容器,当前 statement 创建完成后放入容器中,当下次执行相同的 sql 时会复用 statement 对象,执行完毕后也不会关闭

     

    2》TransactionIsolationLevel

    TransactionIsolationLevel 代表了数据库的隔离级别, 也是一个枚举, 其中包含数据库的四种隔离级别

    NONE: 没有隔离级别

    READ_COMMITTED: 读取提交内容

    READ_UNCOMMITTED: 读取未提交内容

    REPEATABLE_READ: 可重复读

    SERIALIZABLE: 可串行化

     

    3》autoCommit

    第三个参数为是否自动提交事务, 默认不自动提交

    5.2 方法代码解析

    读取 MyBatis-Config.xml 形成 Environment 对象

    final Environment environment = configuration.getEnvironment();
    

    根据 Environment 当作入参, 获取事务工厂

    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    

    事务工厂根据数据源, 数据库隔离级别, 是否自动提交事务标识创建事务对象

    Transactiontx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    

    根据事务对象和不同的执行器类型创建不同的 Mybatis Executor, 通过这里可以得知, 事务和执行器是绑定的

    final Executor executor = configuration.newExecutor(tx, execType);
    

    SqlSession 也是一个接口, DefaultSqlSession 为默认实现类

    根据全局配置对象, 执行器, 是否自动提交事务标识创建 DefaultSqlSession 对象

    return new DefaultSqlSession(configuration, executor, autoCommit)
    

    06、学习总结

    在写这篇文章的时候, 构思的思路本来是挺清晰的, 但是越写感觉知识面越多, 所以只能把构建 SqlSession 主流程写出来

    如果留心或者阅读过 mybatis 源码的同学应该能看出以下几项

    • XMLConfigBuilder 没有说明构建过程

    • Configuration 的对象构建略过

    • Transaction 创建的过程

    不是我不写, 而是: 写出来就是另一个故事了, [捂脸]

     

    <br>

    > 微信搜索【源码兴趣圈】,关注龙台,回复【资料】领取涵盖 GO、Netty、SpringCLoud Alibaba、Seata、开发规范、面试宝典、数据结构等电子书 or 视频学习资料!
     

     

    参考资料

    [1] Mybatis源码地址: https://github.com/mybatis/mybatis-3

    [2] Mybatis官网地址: https://mybatis.org/mybatis-3

    展开全文
  • mybatis 1.mybatis是一个优秀的持久层框架,它支持定制化SQL,存储过程以及高级映射,mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。还可以使用简单的xml或注解来配置和映射原生信息,将接口和java...

    mybatis
    1.mybatis是一个优秀的持久层框架,它支持定制化SQL,存储过程以及高级映射,mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。还可以使用简单的xml或注解来配置和映射原生信息,将接口和java的POJO映射成数据库数据

    2.每个Mybatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionfactoryBuilder获得,SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类实例获得

    3.用xml文件构建SqlSessionFactory实例是非常简单的事情,推荐在这个配置中使用类路径资源(classpath resource),但你可以使用任何Reader实例,包括用文件路径或file://开头的url创建的实例。MyBatis有一个实用类----Resources,它有很多方法,可以方便地从类路径及其它位置加载资源。

    mybatis特点:
    特点:

    1.简单易学:本身小且简单,没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

    2.灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。

    3.解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

    4.提供映射标签,支持对象与数据库的orm字段关系映射

    5.提供对象关系映射标签,支持对象关系组建维护

    6.提供xml标签,支持编写动态sql

    总体流程
    1.加载配置并初始化

    2.接收调用请求

    3.处理·调用请求

    4.返回处理结果将最终的处理结果返回

    功能架构
    1.API接口层

    提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

    2.数据处理层
    负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

    3.基础支撑层
    负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑

    一)、SqlSessionFactoryBuilder
      SqlSessionFactoryBuilder的作用就是在于创建SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder就失去了作用,
    所以它只能存在于创建SqlSessionFactory的方法中,而不要让其长期存在。

    (二)、SqlSessionFactory
      SqlSessionFactory可以被认为是一个数据库连接池,它的作用是创建SqlSession接口对象。因为MyBatis的本质就是Java对数据库的操作,
    所以SqlSessionFactory的生命周期在于于整个MyBatis的应用之中,所以一旦创建了SqlSessionFactory的生命周期就等同于MyBatis的应用周期。

    由于SqlSessionFactory是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个SqlSessionFactory,那么就存在多个数据库连接池,
    这样不利于对数据资源的控制,也会导致连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。因此在一般的应用中我们往往希望SqlSessionfactory作为一个单例,让它在应用中不共享。

    (三)、SqlSession
      如果说SqlSessionFactory相当于数据库连接池,那么SqlSession就相当于一个数据库连接(Connection对象),
    你可以在一个事务里面执行多条SQL,然后通过它的commit、rollback等方法,提交或者回滚事务。所以它应该存活在一个业务请求中,
    处理完整个请求后,应该关闭这条连接,让它归还给SqlSessionFactory,否则数据库资源就很快被消耗精光,系统应付瘫痪,所以用try…catch…fanally语句来保证其正确关闭。

    (四)、Mapper
      Mapper是一个接口,它由SqlSession所创建,所以它的最大生命周期至多和SqlSession保持一致,尽管它很好用,
    但是由于SqlSession关闭,它的数据库连接资源也会消失,所以它的生命周期应该小于等于SqlSession的生命周期。
    Mapper代表是一个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它。

    展开全文
  • SqlSession: 数据库CRUD及事务操作接口 线程不安全,常用于Request范围或method范围 // Request范围,4次sql执行共用一个SqlSession sqlSessionManager.startManagedSession(); try { sqlSessionManager.query1...
  • spring整合mybatis sqlSession释放问题

    千次阅读 2017-10-31 14:20:37
    invoke调用了sqlSession,这个sqlSession实际上是SqlSessionTemplate。这个template的构造函数 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory , ExecutorType executorType , ...
  • 小狼最近在做mybatis的CURD,发现一个小狼不能接受的问题,当然,小狼是比较懒的,见不得冗余代码 每一个CURD操作,小狼都得写一遍下面的代码,一口老血吐出来了...SqlSessionFactoryBuilder ...
  • 一.Mybatis的基本构成:核心组件 1.SqlSessionFactoryBuilder &nbsp;&nbsp;&nbsp;&nbsp; 构造器,根据配置信息负责生成SqlSessionFactory(工厂接口)。 2.SqlSessionFactory &nbsp;&...
  • 生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题 SqlSessionFactoryBuilder: 一旦创建了SqlSessionFactory,就不再需要它了 声明为局部变量 SqlSessionFactory: 可以抽象的想象为:...
  • MyBatis生命周期

    千次阅读 2018-06-25 15:12:24
    在web应用中如果不了解mybatis组件的生命周期可能带来很严重的并发问题,下面总结下SqlSessionFactoryBuilder,SqlSessionFactory,SqlSession和Mapper的生命周期MyBatis核心组件:...
  • Mybatis生命周期

    2019-07-15 19:56:25
    SqlSessionFactory,SqlSession,SqlMapper的生命周期。本文的资料来源是 深入浅出MyBatis技术原理与实战的第二章的第三小节。 需要本书的读者可以通过以下方式获得: 百度云链接 提取码:mq2v ...
  • Mybatis-生命周期

    2019-08-08 20:27:24
    如果开发者不清楚Mybatis组件的生命周期,很可能会带来很严重的并发问题。 SqlSessionFactory 作用 SqlSesssionFactory采用单例模式,唯一的作用是创建SQLSession生命周期 每次应用程序访问数据,我们就要...
  • SSM-Mybatis-生命周期

    2021-02-24 11:55:54
    ​ 可以被理解成一个数据库连接池,用于创建SqlSession接口对象,所以SqlSessionFactory的生命周期等同于Mybatis的应用周期,因为充当着数据库连接池角色,占据着数据库连接资源,如果创建多个可能会导致系统崩
  • 浅谈Mybatis生命周期

    2021-01-24 23:07:06
    浅谈Mybatis生命周期 首先我们从官方文档里面可以看到的是SqlSessionFactoryBuilder使用build来创建SqlSessionFactory,然后SqlSessionFactory再使用openSession开启一个会话连接来创建SqlSession对吧。但是过程并...
  • 之后程序与之打交道的只有SqlSessionFactory 和 SqlSession,因此这个工厂建造者不用给太长的生命周期、太大的作用域。 2.它的生命周期只有在创建SqlSessionFactory工厂时需要,创建完工厂之后可以立即失效
  • mybatis生命周期

    2018-11-16 00:19:20
    MyBatis生命周期  所谓的生命周期就是第一个对象应该存活的时间,比如一些对象一次用完后就要关闭,使它们被Java虚拟机(JVM)销毁,以避免继续占用资源,所以我们会根据每一个组件的作用去确定其生命。 (一)...
  • mybatis组件生命周期

    2018-08-01 12:52:49
    SqlsessionFactoryBuilder...SqlSessionFactory可以被认定为一个数据库连接池,作用是创建sqlsession接口,SqlSessionFactory的生命周期应该是整个mybatisSqlSession相当于传统JDBC中的connection,用完就关掉。...
  • MyBatis生命周期 生命周期就是一个对象创建到销毁的整个过程,同样 来看一下mybatis生命周期是怎么样从创建到销毁的,看看大概 分几下几步: 1、从 XML 中构建 SqlSessionFactory ,获取自定义的配置文件...
  • Mybatis——生命周期和作用域、缓存 工作流程图 由上图可知 生命周期和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题。 1.SqlSessionFactoryBuilder: 一旦创建了 SqlSessionFactory,就不再需要...
  • Mybaits之sqlSession生命周期分析

    万次阅读 2018-12-02 22:40:35
    通过 Mybaits 动态代理,我们了解到Mybaits将接口调用通过反射映射到SqlSession中对应的方法。 那么SqlSession是如果对相关的操作进行处理呢? 跟进Mybaits源码,可以看到SqlSession的一次query执行时序图如下: ...
  • 一、SqlSessionFactoryBuilder SqlSessionFactoryBuilder是利用XML或者Java编码获得资源来构建SqlSessionFactory的,通过它可以构建多个...这时我们就该毫不犹豫的废弃它,将它回收,所以它的生命周期只...
  • 1、MyBatis生命周期 1、SqlSessionFactoryBuilder 2、SqlSessionFactory 3、SqlSession 4、Mapper 2、MyBatis实例 1、配置log4j.properties日志 2、构建POJO对象 3、构建Mapper映射器 4、配置Mapper映射...
  • Mybatis的核心组件有SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper 。 Mybatis的运行流程: SqlSessionFactoryBuilder SqlSessionFactoryBuilder类可以被实例化、使用和丢弃,一旦创建了...
  • 1.生命周期 1.首先通过SqlSessionFactoryBuilder的builde()方法去加载xml文件或者配置文件,会生成一个SqlSessionFactory工厂对象。 2.得到工厂对象后,就可以去工厂里面去拿我们需要的SqlSession对象了,调用...
  • 作用域(Scope)和生命周期 理解我们目前已经讨论过的不同作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。 我们可以先画一个流程图,分析一下Mybatis的执行过程! 作用域理解 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,896
精华内容 3,158
热门标签
关键字:

mybatissqlsession生命周期