由于系统涉及业务太多,数据管理方面也相当复杂,用Spring实现事务管理的时候,如果采用默认的方式,单独给每个业务的 Service 配置代理 Proxy,务必会使配置工作很繁重,但是使用自动配置事务机制以后,一切工作都会很轻松,包括嵌套事务的实现,也相当轻松,
首先,本系统采用的是 业务和事务的并行方式,也就是说 根据现实中的业务来决定事务的大小,尽最大可能避免事务嵌套,但是为了考虑系统的稳定性,把事务配置为支持嵌套的方式!
缺点:测试代码由于只是对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();
}
}
}
测试都很平稳的通过,里面的异常没有特别处理,这里强调的是在事务配置方面,最好把事务配置在业务上,这样业务始终和事务并行,不可能出现事务嵌套!