OpenSessionInViewFilter在网上已经有很多分析资料了,看人家写得那么好,心里痒痒的。于是决定自己也写一篇
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
SessionFactory sessionFactory = lookupSessionFactory(request);
boolean participate = false;
if (isSingleSession()) {
// single session mode
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
participate = true;
}
else {
logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
Session session = getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
}
else {
// deferred close mode
if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
// Do not modify deferred close: just set the participate flag.
participate = true;
}
else {
SessionFactoryUtils.initDeferredClose(sessionFactory);
}
}
try {
filterChain.doFilter(request, response);
}
finally {
if (!participate) {
if (isSingleSession()) {
// single session mode
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
closeSession(sessionHolder.getSession(), sessionFactory);
}
else {
// deferred close mode
SessionFactoryUtils.processDeferredClose(sessionFactory);
}
}
}
}
这里面需要了解几个要点:
1.isSingleSession() 这个默认是true,代表使用OpenSessionInViewFilter
2.TransactionSynchronizationManager.hasResource(sessionFactory)
TransactionSynchronizationManager这个类中有一属性
private static final ThreadLocal resources = new ThreadLocal();
resources 里面存放的是map,而这个map里面存放的是sessionFactory和SessionHolder
public static void bindResource(Object key, Object value) throws IllegalStateException {
Assert.notNull(key, "Key must not be null");
Assert.notNull(value, "Value must not be null");
Map map = (Map) resources.get();
// set ThreadLocal Map if none found
if (map == null) {
map = new HashMap();
resources.set(map);
}
if (map.containsKey(key)) {
throw new IllegalStateException("Already value [" + map.get(key) + "] for key [" + key +
"] bound to thread [" + Thread.currentThread().getName() + "]");
}
map.put(key, value);
if (logger.isDebugEnabled()) {
logger.debug("Bound value [" + value + "] for key [" + key + "] to thread [" +
Thread.currentThread().getName() + "]");
}
}
3.再接着就是比较重要的方法
Session session = getSession(sessionFactory);
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
FlushMode flushMode = getFlushMode();
if (flushMode != null) {
session.setFlushMode(flushMode);
}
return session;
}
因为有属性:private FlushMode flushMode = FlushMode.NEVER;
session.setFlushMode(flushMode);
所以OpenSessionInViewFilter默认的FlushMode 是NEVER
private static Session doGetSession(
SessionFactory sessionFactory, Interceptor entityInterceptor,
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
throws HibernateException, IllegalStateException {
Assert.notNull(sessionFactory, "No SessionFactory specified");
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null && !sessionHolder.isEmpty()) {
// pre-bound Hibernate Session
Session session = null;
if (TransactionSynchronizationManager.isSynchronizationActive() &&
sessionHolder.doesNotHoldNonDefaultSession()) {
// Spring transaction management is active ->
// register pre-bound Session with it for transactional flushing.
session = sessionHolder.getValidatedSession();
if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
TransactionSynchronizationManager.registerSynchronization(
new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
sessionHolder.setSynchronizedWithTransaction(true);
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
// with FlushMode.NEVER, which needs to allow flushing within the transaction.
FlushMode flushMode = session.getFlushMode();
if (flushMode.lessThan(FlushMode.COMMIT) &&
!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.AUTO);
sessionHolder.setPreviousFlushMode(flushMode);
}
}
}
else {
// No Spring transaction management active -> try JTA transaction synchronization.
session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
}
if (session != null) {
return session;
}
}
logger.debug("Opening Hibernate Session");
Session session = (entityInterceptor != null ?
sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());
// Use same Session for further Hibernate actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
SessionHolder holderToUse = sessionHolder;
if (holderToUse == null) {
holderToUse = new SessionHolder(session);
}
else {
holderToUse.addSession(session);
}
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.NEVER);
}
TransactionSynchronizationManager.registerSynchronization(
new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != sessionHolder) {
TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
}
}
else {
// No Spring transaction management active -> try JTA transaction synchronization.
registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
}
// Check whether we are allowed to return the Session.
if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
closeSession(session);
throw new IllegalStateException("No Hibernate Session bound to thread, " +
"and configuration does not allow creation of non-transactional one here");
}
return session;
}
if (sessionHolder != null && !sessionHolder.isEmpty()) 里面的内容感觉只有在多线程并发时才会触发
这里在介绍一个类SessionHolder,这个类用于包装session和transaction
接下来谈下事务和session的关系吧
首先看看Hibernate中对事务的一些方法的封装吧
public void begin() throws HibernateException {
if (begun) {
return;
}
if (commitFailed) {
throw new TransactionException("cannot re-start transaction after failed commit");
}
log.debug("begin");
try {
toggleAutoCommit = jdbcContext.connection().getAutoCommit();
if ( log.isDebugEnabled() ) {
log.debug("current autocommit status: " + toggleAutoCommit);
}
if (toggleAutoCommit) {
log.debug("disabling autocommit");
jdbcContext.connection().setAutoCommit(false);
}
}
catch (SQLException e) {
log.error("JDBC begin failed", e);
throw new TransactionException("JDBC begin failed: ", e);
}
callback = jdbcContext.registerCallbackIfNecessary();
begun = true;
committed = false;
rolledBack = false;
if ( timeout>0 ) {
jdbcContext.getConnectionManager()
.getBatcher()
.setTransactionTimeout(timeout);
}
jdbcContext.afterTransactionBegin(this);
}
jdbcContext.connection()是获取当前数据库的一个连接,大家可以看看c3p0的实现
public class C3P0ConnectionProvider implements ConnectionProvider {
private DataSource ds;
private Integer isolation;
private boolean autocommit;
private static final Log log = LogFactory.getLog(C3P0ConnectionProvider.class);
public Connection getConnection() throws SQLException {
final Connection c = ds.getConnection();
if (isolation!=null) c.setTransactionIsolation( isolation.intValue() );
if ( c.getAutoCommit()!=autocommit ) c.setAutoCommit(autocommit);
return c;
}
最后了解一个东东
Session.setFlushMode()用于设定清理缓存的时间点:
清理缓存的模式 Session的查询方法 Session.commit() Session.flush() FlushMode.AUTO 清理清理清理 FlushMode.COMMIT 不清理清理清理 FlushMode.NEVER 不清理不清理清
分享到:
相关推荐
关于英语四六级的介绍ppt模板,胡扯四六级——关于英语四六级的ppt模板。
PPT模板-胡扯四六级.dpt
可溯金融,驴蒙虎皮,胡扯大旗虚假宣传.docx
【JP摩根-美股-信贷策略-事实还是胡扯:企业信贷中的要素投资调查】这份报告探讨了在企业信贷市场中应用因子投资的实际情况与误区。因子投资是一种投资策略,它允许投资者通过主动管理理解其投资组合的同时,也能...
精品教育教学资料
《Ludum Dare 39:胡扯太空游戏》是一款基于PICO-8虚拟机的独立游戏,由开发者参与Ludum Dare 39游戏创作挑战活动时创作而成。Ludum Dare是一个定期举行的在线游戏制作比赛,挑战者在限定时间内(通常48小时或72小时...
"胡扯"这个词可能是作者自谦或者幽默的表达方式,意味着这个博客系统可能不那么完善或专业,但仍然具有学习和参考价值。 **描述分析:** "CrappyPHP博客,与教程相关的文件将被上传。" 这段描述表明这个项目不仅仅...
而在“BanaBINGO”中,“胡扯的宾果游戏流行语”可能是将数字替换为一些幽默、随机或者与香蕉相关的词汇,增加了游戏的趣味性和娱乐性。 JavaScript作为这个项目的核心技术,主要负责游戏的逻辑处理、用户界面交互...
在"piet:神秘的编程语言Piet的胡扯小编辑器"中,我们有一个专门用于编写和执行Piet代码的工具。 **Piet代码编辑器和口译员** 该编辑器提供了一个交互式的环境,用户可以通过单击指令表来选择对应的颜色,这些颜色...
【neovide】是一款基于Rust编程语言开发的Neovim客户端,它的核心理念是“没有胡扯”,意味着它致力于提供简洁、高效且无冗余功能的编辑器体验。Neovim本身是一款高度可扩展的文本编辑器,而neovide则通过Rust的强...
讲述了英语四级考试流程,时间安排,以及考试各个部分的做题技巧,帮你顺利度过英语四级。
哈伯特宾戈 播放的Hubot脚本流行语胡说的宾果安装在hubot项目存储库中,运行: npm install hubot-bingo --save 然后将hubot-bingo添加到您的external-scripts.json : [ " hubot-bingo " ]样品相互作用user1>> ...
【dj-react-boilerplate:非典型Django + React组合】 在IT行业中,Django和React是两个非常流行的开源框架,分别用于后端开发和前端开发。Django以其强大的功能和安全特性,常被用于构建复杂的数据驱动网站,而...
reCAPTCHA轻量级适应 适用于WordPress的轻量级reCAPTCHA解决方案,例如插件。
【标题】"grail-css" 是一个专门为前端开发者设计的CSS工具库,它提供了一组简单易用且无冗余的CSS助手、重置样式和实用工具类。这个框架的目标是帮助开发者更高效地构建布局,同时保持代码的简洁性和可维护性。...
【d3rink】是一个创新项目,它利用了强大的数据可视化库**d3.js**来创建一个模拟NHL(北美国家冰球联盟)溜冰场的平台。在这个平台上,用户可以自由地在溜冰场上绘制各种数据图形,进行数据可视化的实验和演示。...
这是一个用引导的项目。入门首先,运行开发服务器: npm run dev# oryarn dev 用浏览器打开以查看结果。 您可以通过修改pages/index.js来开始编辑页面。 页面在您编辑文件时自动更新。 可以在上访问。...
欢迎来到React-native-animations :waving_hand: 这是“凤凰”制作的动画的汇编。 他们中有些人很愚蠢,所以不要那么认真。 :stop_sign: 重要的 :stop_sign: 由于某些较早的动画是在复活的Alpha版本中完成的,...
好了,我不胡扯了,这个资源在我CSDN上有免费的(文章),不过比较长,这个是.cpp和.exe都有的,要.h的可以找我要。(好了,上述这么多,想要的我价格不会太高,希望大家给点内个,啊,斯国一,啊对,就是内个三连!...
3. 后真相的四维解读:基恩教授提出后真相包含谎言、胡扯、插科打诨和沉默四个维度。谎言是指明知故犯的虚假陈述;胡扯则涉及不实的自我美化和废话;插科打诨是转移注意力的策略,例如通过笑话和吹嘘来引导公众关注...