Hibernate整合进spring---使用自己的事务处理

1 使用spring的事务处理

spring自带事务处理,使用aop可以在类、方法基于xml和annotation的方式处理事务(详见上文),写下本人的spring使用annotation事务处理:

<!-- transaction -->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
	<aop:pointcut id="serviceOperation1" 
expression="execution(* syx.zswz.service.impl.*.*(..))" />
	<aop:pointcut id="serviceOperation2" 
expression="execution(* syx.zswz.base.DaoBaseImpl.*(..))" />
	<aop:pointcut id="serviceOperation3" 
expression="within(syx.zswz.service..*)" />
	<aop:advisor pointcut-ref="serviceOperation1" 
advice-ref="txAdvice" />
	<aop:advisor pointcut-ref="serviceOperation2" 
advice-ref="txAdvice" />
	<aop:advisor pointcut-ref="serviceOperation3" 
advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice"  transaction-manager="txManager">
	<tx:attributes>
		<tx:method name="*"  />
	</tx:attributes>
</tx:advice>

 

2 使用Hibernate事务处理

因为本人spring事务处理理解的不是很深刻,所以运用起来不是那么得心应手,在加上时间比较紧,所以选择了自己比较熟悉的hbernate事务处理方法(详见上文),因为本项目中使用了spring,所以想把HibernateUtils静态类交给spring处理,在加上filter过滤所有需要事务的请求。但因为原来的filter中使用HibernateUtil是静态类,可以直接调用静态方法,但交给spring处理之后,无法正常给filter注入HibernateUtil,启动tomcat的时候就报异常了。最后使用spring委托的filter,即把filter也交给spring处理,如果没有使用struts的web项目,可以把filter、servlet等都可以交给spring处理:

web.xml

<filter>
	<filter-name>hibernateSessionFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	<init-param>
		<param-name>targetBeanName</param-name>
		<param-value>hibernateSessionFilter</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>hibernateSessionFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

beans.xml部分

<!-- transaction -->
<bean id="hibernateUtils" class="syx.zswz.util.HibernateUtils"></bean>
<bean id="hibernateSessionFilter" 
	class="syx.zswz.filter.HibernateSessionFilter"></bean>

HibernateSessionFilter.java

public void doFilter(ServletRequest request, ServletResponse response,
		FilterChain chain) throws IOException,
		ServletException {
	HttpServletRequest req = (HttpServletRequest) request;
	HttpServletResponse resp = (HttpServletResponse) response;
	String url = req.getRequestURI();// /OA-Study/UserAction!loginUI
	Pattern urlPattern = Pattern.compile("\\w+!\\w+");
	Matcher m = urlPattern.matcher(url);
	if(m.matches()) {	
		Session session = hibernateUtils.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			chain.doFilter(request, response);
			tx.commit();
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			hibernateUtils.closeAndRemoveSession();
		}
	}
}

 

HibernateUtils.java

public class HibernateUtils {
	private  Map<Thread, Session> sessionMap;
	
	@Resource(name="sessionFactory")
	SessionFactory sessionFactory;
	
	public HibernateUtils() {
		sessionMap = new HashMap<Thread, Session>();
		
	}
	static {
	}

	/**
	 * can only use in web filter, beause it should
	 *  remove and clear resources
	 * @return
	 */
	public  Session openSession() {
		System.out.println(Thread.currentThread().getStackTrace()[1] 
			+ " run in " + new Date());
		Session session = sessionMap.get(Thread.currentThread());
		if (session == null) {
			session = sessionFactory.openSession();
			sessionMap.put(Thread.currentThread(), session);
		}
		return session;
	}
	public  Session getCurrentSession() {
		return sessionMap.get(Thread.currentThread());
	}

	public  void closeAndRemoveSession() {
		System.out.println(Thread.currentThread().getStackTrace()[1]
			+ " run in " + new Date());//
		Session session = sessionMap.remove(Thread.currentThread());
		if (session != null) {
			session.close();
		}
	}
}

 

3 hibernate + struts + spring 自己处理事务

如果你们的struts使用了struts,那么所有的action请求,你使用第二种方法是拦截不到的,必须要struts2的Interceptor,在Interceptor中处理每个action的事务:

struts.xml(全局Interceptor):

 

 <package name="admin" namespace="/admin" extends="struts-default">
	<interceptors>
		<interceptor name="hibernateSession" 
class="syx.zswz.filter.HibernateSessionInterceptor"></interceptor>
		<interceptor-stack name="hibernateSessionStack">
		<interceptor-ref name="defaultStack"></interceptor-ref>
		<interceptor-ref name="hibernateSession"></interceptor-ref>
		</interceptor-stack>
	</interceptors>
	
	<default-interceptor-ref name="hibernateSessionStack"></default-interceptor-ref>
</package>

HibernateSessionInterceptor.java

@Override
public String intercept(ActionInvocation actionIvocation) throws Exception {
	String retStr = null;
	Session session = hibernateUtils.openSession();
	Transaction tx = null;
	try {
		tx = session.beginTransaction();
		retStr = actionIvocation.invoke();
		tx.commit();
	} catch (Exception e) {
		if (tx != null) {
			tx.rollback();
		}
		throw new RuntimeException(e);
	} finally {
		hibernateUtils.closeAndRemoveSession();
	}
	return retStr;
}

 

这样每一个struts的action请求过来,就会打开一个session,而请求结束时自动的提交,类似于request级别的session,而且懒加载问题应该也不会有了,因为session还没有commit,这样对于事务处理不是很强的系统可以考虑,当然对于那种事务处理控制很精细可能还要使用spring的事务处理了。

 

注:突然想到了为什么我用spirng事务处理的时候transaction不是很好控制的原因了,可能是:因为我把transaction都是加在service和serviceimpl层和底层的daobase上,而我的action调用service层中方法,可能调用几个方法A、B、C等,类似这种:

XXAction extends ActionSupport {

       public String add() {

                  serviceA.get();

                  serviceA.update();

                  serviceB.save(XX);

        }

}

当我第一个serviceA.get()调用完后,transaction提交,session结束,我serviceA.update()如果在用第一个方法返回的结果,可能会产生意想不到的结果,比如“一个集合不能被2个session处理”异常,我应该把transaction放到Action的方法,这样add方法进入之前打开,add出去关闭,应该是我想要的结果。时间紧,只有等下个项目测试了。

posted @ 2011-11-27 19:38  BuildNewApp  阅读(2416)  评论(0编辑  收藏  举报