Code Bye

spring3.2整合hibernate3.6,AOP事务问题

最近自己搭建了一个ssh的框架,在spring 整合 hibernate这块不是很理解,希望大家帮助我解决问题。
这个是我的spring配置文件,对于hibernate事务,我选择AOP的形式去管理事务

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		classpath:/org/springframework/beans/factory/xml/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context 
		classpath:/org/springframework/context/config/spring-context-3.2.xsd
		http://www.springframework.org/schema/tx 
        classpath:/org/springframework/transaction/config/spring-tx-3.2.xsd
        http://www.springframework.org/schema/aop
        classpath:/org/springframework/aop/config/spring-aop-3.2.xsd">
	<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="com.*"/>  
	<!-- 引用jdbc配置文件 -->
	<context:property-placeholder location="WEB-INF/jdbc.properties"/>
	<!-- 配置数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClassName}"></property>
		<property name="jdbcUrl" value="${jdbc.url}"></property>
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>

	    <property name="acquireIncrement" value="1"></property>  
	    <property name="initialPoolSize" value="5"></property>  
	    <property name="maxIdleTime" value="60"></property>  
	    <property name="maxPoolSize" value="5"></property>  
	    <property name="minPoolSize" value="1"></property>  
	      
	    <property name="acquireRetryDelay" value="1000"></property>  
	    <property name="acquireRetryAttempts" value="60"></property>  
	    <property name="breakAfterAcquireFailure" value="false"></property>  
	</bean>
	<!-- 配置hibernate sessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
		p:mappingLocations="classpath:/com/model/**/*.hbm.xml">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
				</prop>
				<prop key="hibernate.show_sql">
					true
				</prop>
				<!-- 如果没有此配置getCurrentSession()时就会报错:No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here  -->
				<prop key="hibernate.current_session_context_class">
					org.springframework.orm.hibernate3.SpringSessionContext
				</prop>
			</props>
		</property>
	</bean>

	<!-- Transaction Manager 事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!-- 配置事务的传播特性 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" read-only="false" />
			<tx:method name="delete*" propagation="REQUIRED" read-only="false" />
			<tx:method name="update*" propagation="REQUIRED" read-only="false" />
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<!-- 把切面注入到事务中 -->
	<aop:config> 
  		<aop:pointcut id="productServiceMethods" expression="execution(* com.ssh.*.*(..))" /> 
  		<aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods" /> 
	</aop:config> 

</beans>

这是我的dao层基类

public class BaseDao {
	@Resource(name="sessionFactory")
	private SessionFactory sessionFactory;

	protected Session getSession() {
		return sessionFactory.getCurrentSession();
		//return sessionFactory.openSession();
	}

	protected void delete(Object object) {
		this.getSession().delete(object);

	}

	@SuppressWarnings("unchecked")
	protected <T> T get(Class<T> entityClass, long id) {
		return (T) this.getSession().get(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	protected <T> List<T> query(Class<T> entityClass) {
		return this.getSession().createQuery(
				" from " + entityClass.getSimpleName()).list();
	}

	public void save(Object object) {
		Session session = this.getSession();
		session.save(object);
	}

	protected void update(Object object) {
		this.getSession().update(object);

	}

	@SuppressWarnings("unchecked")
	protected <T> T load(Class<T> entityClass, int id) {
		return (T) this.getSession().load(entityClass, id);
	}

	protected void saveOrUpdate(Object object) {
		this.getSession().saveOrUpdate(object);

	}
}

以下,是我的几点疑问:
1.spring的AOP事务管理,是通过匹配对应包下面的方法名称,管理事务的。对于一个业务,只需要一个事务。那么这种AOP方式的配置怎么来控制,一个业务共同拥有一个事务呢?
2.spring管理事务,我如何知道事务什么时候commit,我想要action事务方法执行完以后,当前业务的事务commit,如何办到?当然如果期间有异常,事务rollback是否由spring管理。
3.我写了一个dao层的基类,来集中数据库的操作,当我调用sessionFactory.getCurrentSession()的时候,抛出了org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here,如何解决?我想用spring事务,所以<prop key=”hibernate.current_session_context_class”>thread</prop>不可行
4.ssh整合还有哪些比较精华的部分,希望大家一起来讨论。

在线等,大家帮忙看看
spring AOP自动完成事务的提交和异常回滚
引用 2 楼 splendid_java 的回复:

spring AOP自动完成事务的提交和异常回滚

那么我写的baseDao,getCurrentSession的异常是怎么回事,我的事务已经交给spring管理了

引用 3 楼 wsy2355883 的回复:
Quote: 引用 2 楼 splendid_java 的回复:

spring AOP自动完成事务的提交和异常回滚

那么我写的baseDao,getCurrentSession的异常是怎么回事,我的事务已经交给spring管理了

既然用spring管理事务,为啥不用spring提供的hibernateTemplate或者jdbcTemplate实现数据的操作呢?

1:propagation=”REQUIRED”, 定义了事务的传播途径(调用其它业务时是否开启新的事务等等)。
2:spring AOP自动完成事务的提交和异常回滚
3:你的配置可以啊<prop key=”hibernate.current_session_context_class”>
                    org.springframework.orm.hibernate3.SpringSessionContext
                </prop> 就是告诉hibernate 事务交由spring管理, 也就是通过aop实现hibernate Session的创建和关闭。
引用 5 楼 whos2002110 的回复:

1:propagation=”REQUIRED”, 定义了事务的传播途径(调用其它业务时是否开启新的事务等等)。
2:spring AOP自动完成事务的提交和异常回滚
3:你的配置可以啊<prop key=”hibernate.current_session_context_class”>
                    org.springframework.orm.hibernate3.SpringSessionContext
                </prop> 就是告诉hibernate 事务交由spring管理, 也就是通过aop实现hibernate Session的创建和关闭。

第3个问题,我和你配置的一样,但sessionFactory.getCurrentSession()的时候,抛出了org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here异常,理论上来说,事务已经由spring管理了,为何还会抛出这个异常

引用 4 楼 splendid_java 的回复:
Quote: 引用 3 楼 wsy2355883 的回复:
Quote: 引用 2 楼 splendid_java 的回复:

spring AOP自动完成事务的提交和异常回滚

那么我写的baseDao,getCurrentSession的异常是怎么回事,我的事务已经交给spring管理了

既然用spring管理事务,为啥不用spring提供的hibernateTemplate或者jdbcTemplate实现数据的操作呢?

我想用hibernate API来操作session,这样有更大的灵活性,现在的问题是,我调用getCurrentSession会抛出异常,而我不知道如何解决,希望朋友指点迷津

引用 6 楼 wsy2355883 的回复:
Quote: 引用 5 楼 whos2002110 的回复:

1:propagation=”REQUIRED”, 定义了事务的传播途径(调用其它业务时是否开启新的事务等等)。
2:spring AOP自动完成事务的提交和异常回滚
3:你的配置可以啊<prop key=”hibernate.current_session_context_class”>
                    org.springframework.orm.hibernate3.SpringSessionContext
                </prop> 就是告诉hibernate 事务交由spring管理, 也就是通过aop实现hibernate Session的创建和关闭。

第3个问题,我和你配置的一样,但sessionFactory.getCurrentSession()的时候,抛出了org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here异常,理论上来说,事务已经由spring管理了,为何还会抛出这个异常

那你aop配置是否对呢?  是否已经切在对应方法上? 

引用 8 楼 whos2002110 的回复:
Quote: 引用 6 楼 wsy2355883 的回复:
Quote: 引用 5 楼 whos2002110 的回复:

1:propagation=”REQUIRED”, 定义了事务的传播途径(调用其它业务时是否开启新的事务等等)。
2:spring AOP自动完成事务的提交和异常回滚
3:你的配置可以啊<prop key=”hibernate.current_session_context_class”>
                    org.springframework.orm.hibernate3.SpringSessionContext
                </prop> 就是告诉hibernate 事务交由spring管理, 也就是通过aop实现hibernate Session的创建和关闭。

第3个问题,我和你配置的一样,但sessionFactory.getCurrentSession()的时候,抛出了org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here异常,理论上来说,事务已经由spring管理了,为何还会抛出这个异常

那你aop配置是否对呢?  是否已经切在对应方法上? 

<!– 配置事务的传播特性 –>
<tx:advice id=”txAdvice” transaction-manager=”transactionManager”>
<tx:attributes>
<tx:method name=”save*” propagation=”REQUIRED” read-only=”false” />
<tx:method name=”delete*” propagation=”REQUIRED” read-only=”false” />
<tx:method name=”update*” propagation=”REQUIRED” read-only=”false” />
<tx:method name=”*” read-only=”true” />
</tx:attributes>
</tx:advice>

<!– 把切面注入到事务中 –>
<aop:config> 
   <aop:pointcut id=”productServiceMethods” expression=”execution(* com.ssh.*.*(..))” /> 
   <aop:advisor advice-ref=”txAdvice” pointcut-ref=”productServiceMethods” /> 
</aop:config> 
然后就是帖子中的baseDao的getCurrentSession抛出异常了,我调用的是save方法,和aop的配置也是相符的


40分
expression=”execution(* com.ssh.*.*(..))”   指定的切点是否正确?  就是说是否切到了你的业务方法上?  只有执行了这里aop切入的方法,spring才会开起事务,也就是会创建Hibernate Session, 保证你后面调用getCurrentSession能够获取到Session。

你可以断点到TransactionInterceptor的invoke方法里面,验证你的方法是否被aop切入事务。
还有如果被aop Interceptorlan拦截到的话, 是可以在方法的行号旁边看aop拦截标识的。 一个类似于”(“的符号。

Multiple markers at this line
	- implements com.xxxx.xxx.xxxService.xxxx
	- advised by 
	 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(org.aopalliance.intercept.MethodInvocation)

鼠标放到符号上还有上面的提示哦

引用 10 楼 whos2002110 的回复:

expression=”execution(* com.ssh.*.*(..))”   指定的切点是否正确?  就是说是否切到了你的业务方法上?  只有执行了这里aop切入的方法,spring才会开起事务,也就是会创建Hibernate Session, 保证你后面调用getCurrentSession能够获取到Session。

你可以断点到TransactionInterceptor的invoke方法里面,验证你的方法是否被aop切入事务。
还有如果被aop Interceptorlan拦截到的话, 是可以在方法的行号旁边看aop拦截标识的。 一个类似于”(“的符号。

Multiple markers at this line
	- implements com.xxxx.xxx.xxxService.xxxx
	- advised by 
	 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(org.aopalliance.intercept.MethodInvocation)

鼠标放到符号上还有上面的提示哦

非常感谢你,我这就去试试~嘿嘿

引用 10 楼 whos2002110 的回复:

expression=”execution(* com.ssh.*.*(..))”   指定的切点是否正确?  就是说是否切到了你的业务方法上?  只有执行了这里aop切入的方法,spring才会开起事务,也就是会创建Hibernate Session, 保证你后面调用getCurrentSession能够获取到Session。

你可以断点到TransactionInterceptor的invoke方法里面,验证你的方法是否被aop切入事务。
还有如果被aop Interceptorlan拦截到的话, 是可以在方法的行号旁边看aop拦截标识的。 一个类似于”(“的符号。

Multiple markers at this line
	- implements com.xxxx.xxx.xxxService.xxxx
	- advised by 
	 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(org.aopalliance.intercept.MethodInvocation)

鼠标放到符号上还有上面的提示哦

拦截器没走,而且好像tomcat启动的时候,也没有实例化拦截器,我缺少TransactionInterceptor的配置吗?


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明spring3.2整合hibernate3.6,AOP事务问题