您的位置:首页 > 编程语言 > Java开发

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

2011-11-27 19:38 381 查看
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出去关闭,应该是我想要的结果。时间紧,只有等下个项目测试了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: