`
blue2048
  • 浏览: 182736 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Mybatis深入剖析 - SqlSession的初始化分析

阅读更多

SqlSession的初始化

  •     声明周期-SqlSession为回话声明周期,理论上一次用户请求,即一个线程里只开启一次session,使       用后即关闭
  •     依赖-DefaultSqlSessionFactory为SqlSesson的工场类,看下面的代码,即可知道Configuration,         Executor和Connection为它所依赖对象
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
      boolean autoCommit;
      try {
        autoCommit = connection.getAutoCommit();
      } catch (SQLException e) {
        // Failover to true, as most poor drivers
        // or databases won't support transactions
        autoCommit = true;
      }
      connection = wrapConnection(connection);
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
      Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

 

  • 如何使用:

    原始的使用方式如下,一个线程里的所有数据库操作方法中都需要新开启Session,浪费资源

SqlSession session= sqlSessionFactory.openSession();
UserDao userDao = session.getMapper(UserDao.class);
UserVo vo = new UserVo();
vo.setName("a");
List<UserVo> users = userDao.queryUsers(user);

   

    那我们来看看Spring是如何管理SqlSession的,SqlSessonUtils中获取Session的方法如下,*注解的代码是获取session的核心,其本质是ThreadLocal绑定资源到当前线程上,

 public static SqlSession getSqlSession(
            SqlSessionFactory sessionFactory, 
            ExecutorType executorType, 
            PersistenceExceptionTranslator exceptionTranslator) {
        
        Assert.notNull(sessionFactory, "No SqlSessionFactory specified");
        Assert.notNull(executorType, "No ExecutorType specified");

        //*****************************************************
        SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
        //*****************************************************
        if (holder != null && holder.isSynchronizedWithTransaction()) {
            if (holder.getExecutorType() != executorType) {
                throw new TransientDataAccessResourceException(
                        "Cannot change the ExecutorType when there is an existing transaction");
            }

            holder.requested();
            
            if (logger.isDebugEnabled()) {
                logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");
            }

            return holder.getSqlSession();
        }

        DataSource dataSource = sessionFactory.getConfiguration().getEnvironment().getDataSource();
        
        // SqlSessionFactoryBean unwraps TransactionAwareDataSourceProxies but 
        // we keep this check for the case that SqlSessionUtils is called from custom code
        boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy);
        Connection conn;
        try {
            conn = transactionAware ? dataSource.getConnection() : DataSourceUtils.getConnection(dataSource);
        } catch (SQLException e) {
            throw new CannotGetJdbcConnectionException("Could not get JDBC Connection for SqlSession", e);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Creating SqlSession with JDBC Connection [" + conn + "]");
        }

        // Assume either DataSourceTransactionManager or the underlying
        // connection pool already dealt with enabling auto commit.
        // This may not be a good assumption, but the overhead of checking
        // connection.getAutoCommit() again may be expensive (?) in some drivers
        // (see DataSourceTransactionManager.doBegin()). One option would be to
        // only check for auto commit if this function is being called outside
        // of DSTxMgr, but to do that we would need to be able to call
        // ConnectionHolder.isTransactionActive(), which is protected and not
        // visible to this class.
        SqlSession session = sessionFactory.openSession(executorType, conn);

        // Register session holder and bind it to enable synchronization.
        //
        // Note: The DataSource should be synchronized with the transaction
        // either through DataSourceTxMgr or another tx synchronization.
        // Further assume that if an exception is thrown, whatever started the transaction will
        // handle closing / rolling back the Connection associated with the SqlSession.
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            if (!(sessionFactory.getConfiguration().getEnvironment().getTransactionFactory() instanceof SpringManagedTransactionFactory)
                    && DataSourceUtils.isConnectionTransactional(conn, dataSource)) {
                throw new TransientDataAccessResourceException(
                        "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
            }

            if (logger.isDebugEnabled()) {
                logger.debug("Registering transaction synchronization for SqlSession [" + session + "]");
            }
            holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
            TransactionSynchronizationManager.bindResource(sessionFactory, holder);
            TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
            holder.setSynchronizedWithTransaction(true);
            holder.requested();
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
            }            
        }

        return session;
    }

 

以上代码总结起来, 主要有以下两点

  1. SessionHolder为SqlSession,ExecutorType和ExceptionTranslator的包装类
  2.  以SessionFactory为key,在Thread声明周期里缓存SessionHold

具体Spring trasaction的内部解析请见另一片博客

 

 

    

分享到:
评论

相关推荐

    mybatis-3-config.dtd mybatis-3-mapper.dtd

    首先,让我们深入了解一下`mybatis-3-config.dtd`。这个文件是MyBatis配置文件的DTD,它规定了`mybatis-config.xml`文件中的元素和属性。`mybatis-config.xml`是MyBatis的核心配置文件,它包含了全局设置,如数据源...

    mybatis-spring-1.3.0.jar 下载

    《深入解析mybatis-spring-1.3.0.jar:集成与应用》 在Java开发领域,MyBatis和Spring框架的结合使用是常见的实践,它们的整合使得数据访问层的构建更为便捷和灵活。本篇文章将围绕"mybatis-spring-1.3.0.jar"这一...

    mybatis-spring-1.3.1.jar下载

    2. **配置集成**:在Spring的配置文件中,需要添加MyBatis-Spring的相关配置,包括SqlSessionFactory和MapperScannerConfigurer,以便让Spring知道如何初始化和管理MyBatis的相关组件。 3. **Mapper接口**:创建...

    mybatis-spring-1.2.0.jar

    标题 "mybatis-spring-1.2.0.jar" 提供了我们正在讨论的软件组件的核心信息,即MyBatis-Spring的特定版本——1.2.0。MyBatis-Spring是MyBatis和Spring框架集成的一个库,旨在简化在Spring应用中使用MyBatis的工作。...

    mybatis-3-mybatis-3.2.6

    1. **配置解析**:MyBatis的配置文件(mybatis-config.xml)被解析成Configration对象,这个对象包含了所有的全局配置信息,如数据源、事务管理器、Mappers等。解析过程主要由XMLConfigBuilder类完成。 2. **...

    mybatis-3.2.8 mybatis-3.3.0-SNAPSHOT.jar

    MyBatis的两个关键版本,即mybatis-3.2.8和mybatis-3.3.0-SNAPSHOT,具有各自的特点和改进,以下将详细介绍这两个版本的知识点。 首先,mybatis-3.2.8是MyBatis的一个稳定发布版,主要关注于性能优化和一些bug修复...

    mybatis-spring-1.3.3.jar官方下载

    MyBatis-Spring 是一个将 MyBatis ORM 框架与 Spring 框架集成的库,使得在 Spring 应用中使用 MyBatis 变得更加方便。mybatis-spring-1.3.3.jar 文件是这个集成库的一个版本,提供了对 MyBatis 1.3.3 和 Spring 的...

    mybatis-spring-1.31.jar

    《MyBatis-Spring 1.3.1:构建高效SSM整合的基石》 MyBatis-Spring 1.3.1.jar是MyBatis与Spring框架深度整合的一个重要组件,它允许开发者在Spring环境下无缝地使用MyBatis。这个版本是官方发布的最新稳定版,经过...

    mybatis-3.0.3-SNAPSHOT-bundle.zip

    1. **mybatis-3.0.3-SNAPSHOT.jar**:这是MyBatis的核心库,包含了所有必要的类和接口,如SqlSession, SqlSessionFactory, Executor等,它们是执行数据库操作的基础。 2. **mybatis-3.0.3-SNAPSHOT-sources.jar**:...

    mybatis-3.2.2-src.rar 源码

    这个源码包"mybatis-3.2.2-src.rar"包含了完整的Mybatis 3.2.2版本的源代码,对开发者来说是一份宝贵的学习资源。 源码分析可以从以下几个主要方面展开: 1. **架构设计**:Mybatis 的核心组件包括...

    mybatis-spring-1.1.1-bundle

    本文将深入探讨mybatis-spring-1.1.1版本的集成原理、配置以及实际应用。 1. MyBatis-Spring概述 MyBatis-Spring是MyBatis和Spring之间的粘合剂,它提供了将MyBatis的SqlSession和Mapper接口透明地注入到Spring ...

    MyBatis整合Spring中间件jar包 mybatis-spring-1.3.0.jar

    MyBatis-Spring是MyBatis与Spring框架的整合组件,其主要目的是简化在Spring应用中集成MyBatis的过程,使两者能够无缝协作。mybatis-spring-1.3.0.jar是这个中间件的特定版本,包含了实现这种集成所需的所有类和资源...

    mybatis-enhanced-cache源码和jar包

    而"mybatis-enhanced-cache-master.zip"则可能是源码包,如果你需要深入了解插件的工作原理或者想要对其进行二次开发,可以解压此文件查看源代码。 在实际使用中,你需要按照以下步骤配置和使用这个插件: 1. 添加...

    mybatis-generator-core-1.3.2

    《MyBatis Generator Core 1.3.2:自动化代码生成的艺术》 在Java开发领域,MyBatis Generator(MBG)是一个强大的工具,它极大地简化了数据访问层的编码工作。MyBatis Generator Core 1.3.2是这个框架的一个版本,...

    mybatis-generator-config_1_0dtd网址已经链接不了,这里提供源文件

    貌似http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd已经链接不了,这里提供一个mybatis-generator-config_1_0的dtd文件,替换后就可以使用mybatis自动生成插件了。把网址替换成dtd文件的存放路径就行了,...

    mybatis-spring-1.3.2.zip

    总之,MyBatis-Spring 提供了一种简洁且高效的方式来整合两个流行框架的功能,使开发者能充分利用它们的优点,提高开发效率,同时保持代码的整洁和模块化。在版本 1.3.2 中,可能包含了对之前版本的错误修复、性能...

    mybatis-generator-core.jar包

    为了在项目中使用这个jar,你需要先将`mybatis-generator-core-1.3.2.rar`文件解压缩,然后将解压后的`mybatis-generator-core-1.3.2`目录中的所有文件和子目录打包成一个jar文件。打包过程可以通过命令行工具如`jar...

    mybatis-3-mybatis-3.3.0.zip

    通过解压"Mybatis-3-mybatis-3.3.0.zip",你可以获得完整的MyBatis框架源码,包括核心库、示例项目、文档和测试用例,这对于学习和深入理解MyBatis的工作原理非常有帮助。同时,你可以根据项目需求,将其集成到你的...

    mybatis-spring-1.3.2.jar

    MyBatis-Spring 是一个将 MyBatis ORM 框架与 Spring 框架集成的库,它的主要目标是简化在 Spring 应用中使用 MyBatis 的过程,实现数据访问层(DAO)的无缝集成。这个 `mybatis-spring-1.3.2.jar` 文件就是该集成库...

Global site tag (gtag.js) - Google Analytics