Hibernate-jdon框架事务边界及session的一些讨论

转自jdon论坛 oojdon提问:

//数据库请求到来,从当前ThreadLocal取session并开始事务
public Session getSession() throws HibernateException {  
Session sess = (Session)SessionFactoryHolder.getSession();
if (sess == null) {
sess = getFactory().openSession();

Transaction tr = sess.beginTransaction();

SessionFactoryHolder.setSession(sess);

SessionFactoryHolder.setTransaction(tr);
}
return sess;
}


//CloseSessionInView,提交事务
public void closeSession() throws HibernateException { 

Transaction tr = (Transaction) SessionFactoryHolder.getTransactio();

try {
if (tr != null; !tr.wasCommitted(); !tr.wasRolledBack()) {
tr.commit();
}
} catch (Exception e) {
}finally{
SessionFactoryHolder.setTransaction(null);

SessionFactoryHolder.getSession().close();

SessionFactoryHolder.setSession(null);
}
}


1,没有使用Hibernate的JiveJdon,持久层使用JdbcTemp,没有事务,默认自动提交

public void createTopicMessage(EventModel em) throws Exception { 

ForumMessage forumMessage = (ForumMessage)em.getModelIF();

Forum forum = forumBuilder.getForum(forumMessage.getForu().getForumId());

forumMessage.setForum(forum);

ForumThread forumThread = super.createThread(forumMessage);

forumMessage.setForumThread(forumThread);

messageDaoFacade.getMessageDao().createMessage(forumMessage);

}


2,没有使用Hibernate的JiveJdon,持久层使用JdbcTemp,使用JTA事务接口

public void createTopicMessage(EventModel em) throws Exception { 
ForumMessage forumMessage = (ForumMessage)em.getModelIF();

Forum forum = forumBuilder.getForum(forumMessage.getForum().getForumId());

forumMessage.setForum(forum);

TransactionManager tx = jtaTransactionUtil.getTransactionManager();
try {
tx.begin();

ForumThread forumThread = super.createThread(forumMessage);

forumMessage.setForumThread(forumThread);

messageDaoFacade.getMessageDao().createMessage(forumMessage);

tx.commit();
}catch (Exception e) {
logger.error(e);
jtaTransactionUtil.rollback(tx);
throw new Exception(e);
}
}


3,使用了Hibernate的JiveJdon,使用jdon框架整合Hibernate的事务处理----事务边界是数据库请求—>页面渲染结束

public void createTopicMessage(EventModel em) throws Exception { 

ForumMessage forumMessage = (ForumMessage)em.getModelIF();

Forum forum = forumBuilder.getForum(forumMessage.getForum().getForumId());

forumMessage.setForum(forum);

ForumThread forumThread = super.createThread(forumMessage);

forumMessage.setForumThread(forumThread);

messageDaoFacade.getMessageDao().createMessage(forumMessage);
}


4, 使用了Hibernate的JiveJdon,但手工使用JTA接口

public void createTopicMessage(EventModel em) throws Exception { 
ForumMessage forumMessage = (ForumMessage)em.getModelIF();

Forum forum = forumBuilder.getForum(forumMessage.getForum().getForumId());

forumMessage.setForum(forum);

TransactionManager tx = jtaTransactionUtil.getTransactionManager();
try {
tx.begin();
ForumThread forumThread = super.createThread(forumMessage);

forumMessage.setForumThread(forumThread);

messageDaoFacade.getMessageDao().createMessage (forumMessage);

tx.commit();

} catch (Exception e) {
logger.error(e);
jtaTransactionUtil.rollback(tx);
throw new Exception(e);
}
}


5,jivejdon已经向EJB平滑升级,所以方法是这样的

@TransactionAttribute(REQUIRES_NEW) 

public void createTopicMessage(EventModel em) throws Exception {

ForumMessage forumMessage = (ForumMessage)em.getModelIF();

Forum forum = forumBuilder.getForum(forumMessage.getForum().getForumId());

forumMessage.setForum(forum);

ForumThread forumThread = super.createThread(forumMessage);

forumMessage.setForumThread(forumThread);

messageDaoFacade.getMessageDao().createMessage(forumMessage);
}


我比较郁闷的就是这四,五两种写法,事务在方法返回后结束,但是Hibernate的sessin呢?是还打开,还是已经被关闭,如果关闭我的懒加载怎么办?

banq等回复:
我也赞成使用第四 五种方式,在这两个方式下,我前面帖子写了,不必关闭session的两种方式处理事务和Session的关系:
1. 手工在事务结束前session.flush()
2. 配置Hibernate的transaction.mamager为JTA,让Hibernete能够自动进行flush,它会侦测当前是否在一个事务,如果事务结束,它就进行flush,将内存中状态和数据库数据进行同步。

事务和Session本来特别关系,事务主要是保证数据库资源操作的一致性,所以,需要flush来特别操作。

不要将事务搞神秘,事务基本只有两个JTA长事务(包括跨段2PC事务)和JDBC短事务,Hibernate本质就是JDBC+缓存。事务是JavaEE基础功能,可以下载JavaEE标准看看,和任何框架都不搭架(除非专门提供事务的框架)。

Spring和EJB一样,只是提供事务的AOP切入方式,也就是说,无需自己手工写transaction.begin,因为AOP拦截器做了。Spring本身没有提供除JTA/JDBC事务以外任何神秘新的功能。

如果了解AOP,就知道:transaction.begin不在当前程序写,只是移到拦截器中写,写的地方不一样了。这就是区别,因为不需要你在程序自己写transaction.begin(这叫显式调用),也就是隐式调用JTA了,从你眼前隐去了。这个区别就是对JTA事务调用方式的不同,而不是JTA事务本身的不同,不要将这两者混同在一起。

不要把"JPA、Hibernate、JDO和JTA"混同在一起,JTA是JavaEE基础功能,而JPA、Hibernate、JDO只是持久化框架,和JTA无关。也就是说,JPA、Hibernate、JDO没有JTA也可以用,JTA没有JPA、Hibernate、JDO也可以用。

所以,如果你搞不定JTA,就不急于使用它。JTA通常在Service或业务层来使用(transaction.beigin显式调用或AOP/EJB的隐式调用),可以跨多个JDBC或其他资源,这个可以参考本站事务标签了解一下。

因为JTA在业务层使用,才可能和Spring/EJB这样框架有点关系,这个关系也就是显式调用或隐式调用的关系,就像两个男女,本是独立的,发生关系了,要么是显式声明的,登记结婚大张旗鼓(表现为需要写代码),要么就是偷情隐式的,悄悄的(表现为不需要写代码了)。

事务是JavaEE中最复杂的知识,它和原子性 多线程 锁等有关(所以才有取款机吐钱,记录数据没变化等不一致性,这些都充分说明国人对事务安全非常薄弱),说大了也和并行计算有关(在多个CPU同时执行你的程序情况下,如何保证你业务真正原子性和唯一性,又不能丧失多线程多核的优势。)。这个世界上最缺的就是编写并发计算的人,这是有道理的。

另外,要注意:框架和JavaEE组件要有区分。框架实际就是把这些组件扒拉扒拉在一起,方便或约束你使用,从设计上让你的程序更所谓优雅,当然也有弄巧成拙,搞复杂了,Spring至少是这样,一些人以为复杂就是优雅实际被误导(最可悲就是不自知),所以Spring没热多长时间,Ruby on Rails以其简洁性成为热点,这是有原因的,现在Scala又开始热起来,因为大家发现RoR慢啊,如果能够使用多核的DSL多好啊,设计又优雅性能又优雅,双优雅,这才是真优雅。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值