配置sqlsessiontemplate有啥用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了配置sqlsessiontemplate有啥用相关的知识,希望对你有一定的参考价值。

工作中,需要学习一下MyBatis sqlSession的产生过程,翻看了mybatis-spring的源码,阅读了一些mybatis的相关doc,对mybatis sqlSession有了一些认知和理解,这里简单的总结和整理一下。

首先, 通过翻阅源码,我们来整理一下mybatis进行持久化操作时重要的几个类:
SqlSessionFactoryBuilder:build方法创建SqlSessionFactory实例。
SqlSessionFactory:创建SqlSession实例的工厂。

SqlSession:用于执行持久化操作的对象,类似于jdbc中的Connection。
SqlSessionTemplate:MyBatis提供的持久层访问模板化的工具,线程安全,可通过构造参数或依赖注入SqlSessionFactory实例。

Hibernate是与MyBatis类似的orm框架,这里与Hibernate进行一下对比,Hibernate中对于connection的管理,是通过以下几个重要的类:
SessionFactory:创建Session实例的工厂,类似于MyBatis中的SqlSessionFactory。
Session:用来执行持久化操作的对象,类似于jdbc中的Connection。

HibernateTemplate:Hibernate提供的持久层访问模板化的工具,线程安全,可通过构造参数或依赖注入SessionFactory实例。

在日常的开发中,我们经常需要这样对MyBatis和Spring进行集成,把sqlSessionFactory交给Spring管理,通常情况下,我们这样配置:
?

1
2
3

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

通过上面的配置,Spring将自动创建一个SqlSessionFactory对象,其中使用到了org.mybatis.spring.SqlSessionFactoryBean,其 是MyBatis为Spring提供的用于创建SqlSessionFactory的类,将在Spring应用程序的上下文建议一下可共享的 MyBatis SqlSessionFactory实例,我们可以通过依赖注入将SqlSessionFactory传递给MyBatis的一些接口。

如果通过Spring进行事务的管理,我们需要增加Spring注解的事务管理机制,如下配置:
?

1
2
3
4
5

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<tx:annotation-driven/>

这样,我们就可以使用Spring @Transactional注解,进行事务的控制,表明所注释的方法应该在一个事务中运行。 Spring将在事务成功完成后提交事务,在事务发生错误时进行异常回滚,而且,Spring会将产生的MyBatis异常转换成适当的 DataAccessExceptions,从而提供具体的异常信息。

下面,我们通过分析SqlSessionUtils中getSession的源码,来详细的了解一下sqlSession的产生过程,源码如下:
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator)

notNull(sessionFactory, "No SqlSessionFactory specified");
notNull(executorType, "No ExecutorType specified");

SqlSessionHolder holder = (SqlSessionHolder) 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();


if (logger.isDebugEnabled())
logger.debug("Creating a new SqlSession");


SqlSession session = sessionFactory.openSession(executorType);

// Register session holder if synchronization is active (i.e. a Spring TX is active)
//
// Note: The DataSource used by the Environment 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 (isSynchronizationActive())
Environment environment = sessionFactory.getConfiguration().getEnvironment();

if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory)
if (logger.isDebugEnabled())
logger.debug("Registering transaction synchronization for SqlSession [" + session + "]");


holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
bindResource(sessionFactory, holder);
registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
holder.setSynchronizedWithTransaction(true);
holder.requested();
else
if (getResource(environment.getDataSource()) == null)
if (logger.isDebugEnabled())
logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");

else
throw new TransientDataAccessResourceException(
"SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");


else
if (logger.isDebugEnabled())
logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");



return session;


上面的getSession方法,会从Spring的事务管理器中获取一个SqlSession或创建一个新的SqlSession,将试图从当前事务中得到一个SqlSession,然后,如果配置有事务管理器的工厂并且Spring 的事务管理器是活跃的,它将会锁定当前事务的SqlSession,保证同步。主要是通过以下几个步骤进行SqlSession的创建:
它会首先获取SqlSessionHolder,SqlSessionHolder用于在TransactionSynchronizationManager中保持当前的SqlSession。
如果holder不为空,并且holder被事务锁定,则可以通过holder.getSqlSession()方法,从当前事务中获取sqlSession,即 Fetched SqlSession from current transaction。

如果不存在holder或没有被事务锁定,则会创建新的sqlSession,即 Creating a new SqlSession,通过sessionFactory.openSession()方法。

如果当前线程的事务是活跃的,将会为SqlSession注册事务同步,即 Registering transaction synchronization for SqlSession。
参考技术A

SqlSessionTemplate是MyBatis-Spring的核心。这个类负责管理MyBatis的SqlSession,调用MyBatis的SQL方法,翻译异常。SqlSessionTemplate是线程安全的,可以被多个DAO所共享使用。

当调用SQL方法时,包含从映射器getMapper()方法返回的方法,SqlSessionTemplate将会保证使用的SqlSession是和当前Spring的事务相关的。此外,它管理session的生命周期,包含必要的关闭,提交或回滚操作。

SqlSessionTemplate实现了SqlSession,这就是说要对MyBatis的SqlSession进行简易替换。

SqlSessionTemplate通常是被用来替代默认的MyBatis实现的DefaultSqlSession,因为它不能参与到Spring的事务中也不能被注入,因为它是线程不安全的。相同应用程序中两个类之间的转换可能会引起数据一致性的问题。

SqlSessionTemplate对象可以使用SqlSessionFactory作为构造方法的参数来创建。

 

java开发工具包安装好后配置环境变量有啥用?

那为什么在桌面上的name.java程序不能编译运行呢?

参考技术A 环境变量帮你找到java运行的环境,从而运行java程序。
.java文件是源代码,要编译成.class文件才能运行。类似于c程序要编译成.exe才能运行。
参考技术B 桌面上的name.java程序可以编译啊,如下:
C:\Documents and Settings\All Users\桌面>javac name.java
C:\Documents and Settings\All Users\桌面>java name

路径一定要正确,你把name.java放到桌面,并不是你眼前看到的那个桌面上的,而是在C:\Documents and Settings\All Users\桌面>这个文件夹里存放了你的name.java文件

楼主,现在清楚了吗?

配置环境变量是为了:设置供操作系统去寻找和执行应用程序的路径。本回答被提问者采纳
参考技术C 能让系统找到编译运行工具,和类路径 参考技术D 配置了你才能编译java代码`开发东西

以上是关于配置sqlsessiontemplate有啥用的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis-Spring的sqlSessionTemplate

java开发工具包安装好后配置环境变量有啥用?

Spring Boot 2.5.0 重新设计的spring.sql.init 配置有啥用?

面试精选ZooKeeper 的典型应用场景发布订阅功能有啥用?

vmware esxi 有啥用

配置java_home到底有啥用?为啥tomcat一定要配置它?