Spring嵌套事务的两种事务管理配置方式

由于系统涉及业务太多,数据管理方面也相当复杂,用Spring实现事务管理的时候,如果采用默认的方式,单独给每个业务的 Service 配置代理 Proxy,务必会使配置工作很繁重,但是使用自动配置事务机制以后,一切工作都会很轻松,包括嵌套事务的实现,也相当轻松,网上流动许多关于Spring事务配置的帖子,但是都很不完全,缺东少西,也给许多爱好者带来不便,下面将这两天的调试结果写下,希望对朋友们有所帮助!

 

首先,本系统采用的是 业务和事务的并行方式,也就是说 根据现实中的业务来决定事务的大小,尽最大可能避免事务嵌套,但是为了考虑系统的稳定性,把事务配置为支持嵌套的方式!

 

缺点:测试代码由于只是对spring的事务进行测试,所以异常没有特别处理,包括其他的代码,都是个人在私下编写,仅供朋友们参考!

 

测试设计:

1:业务接口:

package ioc;

public interface CategoryService
{
 public void save(Parameter para) throws Exception;
}
2:业务实现

package ioc;


public class CategoryBiz implements CategoryService
{

 private CategoryManager categoryManager = null;

 public void save(Parameter para) throws Exception
 {

   //implements
  //
  categoryManager.save(c);
 }

 public CategoryManager getCategoryManager()
 {
  return categoryManager;
 }

 public void setCategoryManager(CategoryManager categoryManager)
 {
  this.categoryManager = categoryManager;
 }

}
3:持久管理接口,持久实体 Category

package ioc;

public interface CategoryManager
{
 public void save(Category category) throws Exception;
}
4:持久管理实现

package ioc;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class package ioc;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class CategoryDAO extends HibernateDaoSupport implements CategoryManager
{

 public void save(Category category) throws Exception
 {
  try
  {
   this.getHibernateTemplate().save(category);
  }
  catch (Exception e)
  {
   throw e;
  }
 }

}
5:bean 管理工厂

这里暂时采用饿汉方式实现:朋友们也可以采用懒汉方式实现。

package ioc;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanFactory
{

 private static ApplicationContext applicationContext = null;

 private static BeanFactory self = null;
 static
 {
  if (applicationContext == null)
  {
   try
   {
    applicationContext = new ClassPathXmlApplicationContext(
      "ioc/applicationContext.xml");
   }
   catch (BeansException e)
   {
    e.printStackTrace();
   }
  }
 }

 synchronized public static BeanFactory getInstance()
 {
  if (self == null)
  {
   self = new BeanFactory();
  }
  return self;
 }

 public Object getBeanById(String beanId)
 {
  Object bean = null;
  try
  {
   bean = applicationContext.getBean(beanId);
  }
  catch (BeansException e)
  {
   e.printStackTrace();
  }
  return bean;
 }


}

6:标准context配置文件 applicationProxyContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

 <bean id="SessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="configLocation">
   <value>ioc/hibernate.cfg.xml</value>
  </property>
 </bean>
 <bean id="TransactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="SessionFactory" />
 </bean>

 <!--逐个配置代理模式 事务和业务并行,支持事务嵌套 -->
 <bean id="CategoryManager" class="ioc.CategoryDAO">
  <property name="sessionFactory" ref="SessionFactory" />
 </bean>
 <bean id="CategoryService" class="ioc.CategoryBiz">
  <property name="categoryManager" ref="CategoryManager" />
 </bean>

 <bean id="CategoryServiceProxy"
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <property name="proxyInterfaces">
   <list>
    <value>ioc.CategoryService</value>
   </list>
  </property>
  <property name="target">
   <ref bean="CategoryService" />
  </property>
  <property name="transactionAttributes">
   <props>
    <prop key="save*">
     PROPAGATION_NESTED,-java.lang.Exception
    </prop>
   </props>
  </property>
  <property name="transactionManager">
   <ref bean="TransactionManager" />
  </property>
 </bean>

</beans>
7:标准配置测试:

package ioc;

import java.util.Date;

public class ServiceProxyTest
{
 public static void main(String[] s) throws Exception
 {
  try
  {
   BeanFactory beanFactory = BeanFactory.getInstance();
   //
   CategoryService categoryService = (CategoryService) beanFactory
     .getBeanById("CategoryServiceProxy");
   //implements
   //
   categoryService.save(form);
   System.out.println("service proxy save ok!");
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }

 }

}
8:自动代理配置模式:applicationContext.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

 <bean id="SessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="configLocation" value="ioc/hibernate.cfg.xml" />
 </bean>
 <bean id="TransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="SessionFactory" />

   <!-- 注意:下边这个属性一定不要少,把嵌套事务的开关打开-->
  <property name="nestedTransactionAllowed" value="true" />
 </bean>
 <!--  PROPAGATION_NESTED -->
 <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager" ref="TransactionManager" />
  <property name="transactionAttributes">
   <props>
    <prop key="save*">PROPAGATION_NESTED</prop>
    <prop key="del*">PROPAGATION_NESTED</prop>
    <prop key="update*">PROPAGATION_NESTED</prop>
   </props>
  </property>
 </bean>

 <!-- 自动代理配置,事务和业务并行,支持嵌套事务 -->
 <bean id="BeanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="beanNames">
   <value>*Service</value>
  </property>
  <property name="interceptorNames">
   <list>
    <value>transactionInterceptor</value>
   </list>
  </property>
 </bean>

 <bean id="CategoryManager" class="ioc.CategoryDAO">
  <property name="sessionFactory" ref="SessionFactory" />
 </bean>
 <bean id="CategoryService" class="ioc.CategoryBiz">
  <property name="categoryManager" ref="CategoryManager" />
 </bean>

 

</beans>
9:自动代理 BeanNameAutoProxyCreator 配置模式测试 :

package ioc;

import java.util.Date;

public class CategoryServiceTest
{
 public static void main(String[] s) throws Exception
 {
  try
  {
   BeanFactory beanFactory = BeanFactory.getInstance();
   //
   CategoryService categoryService = (CategoryService) beanFactory
     .getBeanById(CategoryService.class.getSimpleName());
   //implements
   //
   categoryService.save(form);
   System.out.println("service save ok!");
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }

 }

}
测试都很平稳的通过,里面的异常没有特别处理,这里强调的是在事务配置方面,最好把事务配置在业务上,这样业务始终和事务并行,不可能出现事务嵌套!

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页