0 0

Spring事务中奇怪的transactions2次的问题30

Spring与Hibernate集成

Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
	<context:annotation-config />
	<context:component-scan base-package="net.duohuo"></context:component-scan>
	<aop:aspectj-autoproxy />

	 <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation"    value="file:src/hibernate.cfg.xml"/>
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
     </bean>
    
    <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    	<property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
  	<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
	
	

</beans>
 

DAO层测试代码如下

 

package net.duohuo.hibernate.dao.impl;

import javax.annotation.Resource;

import net.duohuo.hibernate.bean.User;
import net.duohuo.hibernate.dao.UserDao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class UserDaoImpl extends HibernateDaoSupport implements UserDao{
	@Resource(name="sessionFactory")
	public void setBaseDaoSessionFactory(SessionFactory baseDaoSessionFactory) {
		super.setSessionFactory(baseDaoSessionFactory);
	}
	
	
	@Override
	public void add() {
		this.getHibernateTemplate().save(new User("xxx"));
	}

}

 写了一个测试类

package net.duohuo.hibernate.test;

import net.duohuo.hibernate.bean.User;
import net.duohuo.hibernate.dao.UserDao;
import net.duohuo.hibernate.util.HibernateSessionFactory;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testSession {
	public void runwithoutSpring(){
		SessionFactory sf=HibernateSessionFactory.getSessionFactory();
		Session session=sf.openSession();
		
		session.beginTransaction();
		session.save(new User("xxx"));
		session.getTransaction().commit();
		session.close();
		
		Statistics stat=sf.getStatistics();
		System.out.println(stat);
	}
	public void runwithSpring(){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao dao=(UserDao)ctx.getBean("userDaoImpl");
		dao.add();
		SessionFactory fac=(SessionFactory)ctx.getBean("sessionFactory");
		Statistics stat=fac.getStatistics();
		System.out.println(stat);
	}
	public static void main(String args[]) {
		testSession test=new testSession();
		test.runwithoutSpring();
		test.runwithSpring();
}
}

 输出结果

Hibernate: insert into test.user (name) values (?)
Statistics[start time=1299479596150,sessions opened=1,sessions closed=1,transactions=1,successful transactions=1,optimistic lock failures=0,flushes=1,connections obtained=1,statements prepared=1,statements closed=1,second level cache puts=0,second level cache hits=0,second level cache misses=0,entities loaded=0,entities updated=0,entities inserted=1,entities deleted=0,entities fetched=0,collections loaded=0,collections updated=0,collections removed=0,collections recreated=0,collections fetched=0,queries executed to database=0,query cache puts=0,query cache hits=0,query cache misses=0,max query time=0]
Hibernate: insert into test.user (name) values (?)
Statistics[start time=1299479597185,sessions opened=1,sessions closed=1,transactions=2,successful transactions=1,optimistic lock failures=0,flushes=1,connections obtained=1,statements prepared=1,statements closed=1,second level cache puts=0,second level cache hits=0,second level cache misses=0,entities loaded=0,entities updated=0,entities inserted=1,entities deleted=0,entities fetched=0,collections loaded=0,collections updated=0,collections removed=0,collections recreated=0,collections fetched=0,queries executed to database=0,query cache puts=0,query cache hits=0,query cache misses=0,max query time=0]

这里用Spring进行事务管理时有两次transactions,换用XML配置事务时也是一样,求解!


问题补充:<div class="quote_title">zzzlyr 写道</div><div class="quote_div"> getCurrentSession() 用这个试一试,别用openSession()这个。 <br /> <br />你的事物已经让Spring 自动管理了。为什么还有在程序里边起动事物,在关呢。 <br /> <br />你在DAO层上整个类都加上事物的注解了@Transactional,应该不需要自己手动开启事物和关闭事物了吧! <br /></div> <br />runwithoutSpring()方法是用原始的Hibernate获取Session开启事务,保存,提交的。而runwithSpring()方法直接调用Dao中的方法的。

问题补充:还有在取消Dao层事务注解的时候事务没有提交,但Statistics打印出来,transactions=1,successful transactions=0。一旦加了注解就变成了transactions=2,successful transactions=1不晓得为什么

问题补充:<div class="quote_title">dwangel 写道</div><div class="quote_div">因为你在DAO类声明了@Transaction, <br />你看下HibernateTemplate的源代码就可以发现 <br />HibernateTemplate的save方法,最终会新建一个Session,新开一个事务,直到提交。 <br />那么事务建立就有两次: <br />Dao调用的proxy,HibernateTemplate.save</div> <br />可是问题是我将Dao类中的方法中的内容save都注释了,什么都不执行。他还是会打印出 <br />sessions opened=1,sessions closed=1,transactions=2,successful transactions=1,难道是@Transactional注解与继承了HibernateDaoSupport的原因?

问题补充:<div class="quote_title">eclipse_vic 写道</div><div class="quote_div">@Transactional&nbsp; <br />和后面的 begin ,启动了两次了!</div> <br />各位大哥,带begin的那个方法是我单独写出来对比的呀。。。

问题补充:研究了下,在配置Spring声明事务时,Spring在方法运行前检查当前线程是否绑定了session,而如果没有绑定则open一个放入SessionFactoryUtils的ThreadLocal中,这个绑定到当前线程的session的是需要使用SessionFactoryUtils获取的。通过查看HibernateDaoSupport的源码发现它集成了SessionFactoryUtils,HibernateDaoSupport的getSession源码如下 <br /><pre name="code" class="java">
#  protected final Session getSession(boolean paramBoolean) 
#     throws DataAccessResourceFailureException, IllegalStateException 
#   { 
#     return ((!(paramBoolean)) ? SessionFactoryUtils.getSession(getSessionFactory(), false) : SessionFactoryUtils.getSession(getSessionFactory(), this.hibernateTemplate.getEntityInterceptor(), this.hibernateTemplate.getJdbcExceptionTranslator())); 
#   }
</pre> <br />相当于获取了这个绑定当前线程的currentSession,如果没有则由SessionFactoryUtils创建一个放入ThreadLocal。 <br />我把@Transactional去掉,注意现在完全是手动控制事务哦!dao中的代码如下 <br /><pre name="code" class="java">
public void create(Object basebean) {
Session session=this.getSession();
Transaction tx=session.beginTransaction();
tx.commit();
//this.releaseSession(session);
}
</pre> <br />这里故意没有关session <br />Status打印出sessions opened=1,sessions closed=0,transactions=1,successful transactions=1 <br />把上面的注释去掉 <br />Status打印出sessions opened=1,sessions closed=1,transactions=2,successful transactions=1 <br />奇怪的transactions=2出现了。。。。。 <br /><pre name="code" class="java">
#  protected final void releaseSession(Session paramSession) 
#   { 
#     SessionFactoryUtils.releaseSession(paramSession, getSessionFactory()); 
#   }
</pre> <br />看来基本上是Spring在关闭session时自动又commit了一次造成的
2011年3月07日 14:42

9个答案 按时间排序 按投票排序

0 0

 <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
你配置的就是hibernate事物管理。。。。

2011年3月09日 00:46
0 0

@Transactional 
和后面的 begin ,启动了两次了!

2011年3月08日 17:32
0 0

你手动整了个session,系统给你open了个session!
不用运行都知道是几个!汗...

2011年3月08日 16:24
0 0

应该是@Transactional的作用吧。
继承应该不影响的。

2011年3月08日 13:13
0 0

貌似如果用HibernateTemplate的save,其实不用自己管理事务?

2011年3月08日 11:47
0 0

因为你在DAO类声明了@Transaction,
你看下HibernateTemplate的源代码就可以发现
HibernateTemplate的save方法,最终会新建一个Session,新开一个事务,直到提交。
那么事务建立就有两次:
Dao调用的proxy,HibernateTemplate.save

2011年3月08日 11:45
0 0

你写的测试方法,一个是spring 自动管理事物,一个是相当于编程式事物(程序控制)!

1: public void runwithoutSpring()这个方法,无论你加不注解,都会事物提交,因为是你自己手动控制事物,跟Spring就无关了。

2: public void runwithSpring()方法,才是声明式事物,不用自己管理,只要配好相应的配置,spring 会自动管理,如果uncheck Exception  它会回滚掉

      test.runwithoutSpring();  
       test.runwithSpring();  

这好像是两个方法一起测试吧,你一个一个测试试一试。此回落只供参考,你试一下吧,不见的我说的对


2011年3月08日 10:24
0 0

http://today.java.net/pub/a/today/2006/08/31/jotm-transactions-in-spring-and-hibernate.html
参考这个...

2011年3月07日 17:14
0 0

getCurrentSession() 用这个试一试,别用openSession()这个。

你的事物已经让Spring 自动管理了。为什么还有在程序里边起动事物,在关呢。

你在DAO层上整个类都加上事物的注解了@Transactional,应该不需要自己手动开启事物和关闭事物了吧!

2011年3月07日 16:34

相关推荐

Global site tag (gtag.js) - Google Analytics