zoukankan      html  css  js  c++  java
  • 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出去关闭,应该是我想要的结果。时间紧,只有等下个项目测试了。

  • 相关阅读:
    Orchard源码分析(4.3):Orchard.Events.EventsModule类(Event Bus)
    Orchard源码分析(4.2):Orchard.Logging.LoggingModule类
    Orchard源码分析(4.1):Orchard.Environment.CollectionOrderModule类
    Orchard源码分析(4):Orchard.Environment.OrchardStarter类
    Orchard源码分析(3):Orchard.WarmupStarter程序集
    Orchard源码分析(2):Orchard.Web.MvcApplication类(Global)
    MSSQL
    MSSQL
    C#、WinForm、ASP.NET
    C#、WinForm、ASP.NET
  • 原文地址:https://www.cnblogs.com/syxchina/p/2265220.html
Copyright © 2011-2022 走看看