设为首页 收藏本站
查看: 1475|回复: 0

[经验分享] Mybatis深入剖析

[复制链接]

尚未签到

发表于 2016-11-28 09:46:02 | 显示全部楼层 |阅读模式
  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;
}
  以上代码总结起来, 主要有以下两点


  • SessionHolder为SqlSession,ExecutorType和ExceptionTranslator的包装类
  •  以SessionFactory为key,在Thread声明周期里缓存SessionHold
  具体Spring trasaction的内部解析请见另一片博客

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-306493-1-1.html 上篇帖子: mybatis 解决特殊参数(" ,')输入报错 下篇帖子: ExtJs+struts+spring+mybatis通用管理后台程序框架
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表