事务的传播行为
一个事务方法调用另一个事务方法时,如何进行事务控制。是做为外部事务的整体控制?还是做为内部事务的部分控制?
在@Transactional注解中,使用propagation属性指导事务的传播行为。
//required -- 有事务就行(事务默认传播行为) @Transactional(propagation=Propagation.REQUIRED) //required new -- 使用自己的事务,外面调用的方法的事务被挂起,相当于外面的事务失效 @Transactional(propagation=Propagation.REQUIRES_NEW)
下一面看一个实例:
1.做两个接口IInfoDao和IWorkDao
package maya.dao; public interface IInfoDao { public void delete(String code); }
package maya.dao; public interface IWorkDao { public void deleteByInfoCode(String code); }
2.做两个类继承以上两个接口:InfoDao和WorkDao
package maya.daolmpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import maya.dao.IInfoDao; @Repository public class InfoDao implements IInfoDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public void delete(String code) { //添加一个判定条件,制造一个错误 if (code.equals("p009")) { int n = 5/0; } String sql = "delete from info where code=?"; jdbcTemplate.update(sql,code); } }
package maya.daolmpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import maya.dao.IWorkDao; @Repository public class WorkDao implements IWorkDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public void deleteByInfoCode(String code) { String sql = "delete from work where infoCode=?"; jdbcTemplate.update(sql,code); } }
3.向xml文件 添加配置信息
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!--启动自动扫描。扫描以下包里的类,以备使用--> <context:component-scan base-package="maya.daolmpl,maya.servicelmpl"></context:component-scan> <!--引入db.properties文件--> <context:property-placeholder location="classpath:db.properties"/> <!-- 生成连接池 --> <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource"> <property name="driverClass" value="${driverClass}"></property> <property name="jdbcUrl" value="${jdbcUrl}"></property> <property name="user" value="${user}"></property> <property name="password" value="${password}"></property> <property name="minPoolSize" value="${minPoolSize}"></property> <property name="maxPoolSize" value="${maxPoolSize}"></property> <property name="initialPoolSize" value="${initialPoolSize}"></property> </bean> <!-- 生成jdbcTemplate --> <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事务管理器 --> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 启动事务注解 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
4.1建立业务接口并用类继承
IInfoService接口
package maya.service; public interface IInfoService { public void delete(String code); }
InfoService类
package maya.servicelmpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import maya.dao.IInfoDao; import maya.dao.IWorkDao; import maya.daolmpl.WorkDao; import maya.service.IInfoService; @Service public class InfoService implements IInfoService { @Autowired private IWorkDao workDao; @Autowired private IInfoDao infoDao; //有事务就行(事务默认传播行为) @Transactional(propagation=Propagation.REQUIRED) @Override public void delete(String code) { workDao.deleteByInfoCode(code); infoDao.delete(code); } }
5.创建测试类并运行
package maya.servicelmpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import maya.service.IInfoService; @Component public class TestAll { @Autowired private IInfoService infoService; @Transactional public void deleteMany() { infoService.delete("p008"); infoService.delete("p009"); } }
package maya.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import maya.dao.IInfoDao; import maya.dao.IWorkDao; import maya.service.IInfoService; import maya.servicelmpl.TestAll; public class Test { private static ApplicationContext context = null; private static IInfoDao infoDao = null; private static IWorkDao workDao = null; private static IInfoService infoService = null; private static TestAll testAll = null; static { context = new ClassPathXmlApplicationContext("beans.xml"); infoDao = (IInfoDao)context.getBean("infoDao"); workDao = (IWorkDao)context.getBean("workDao"); infoService = (IInfoService)context.getBean("infoService"); testAll = (TestAll)context.getBean("testAll"); } public static void main(String[] args) { testAll.deleteMany(); } }
运行结果:”p008“、“p009”未被删除
4.2设置使用自己的事务,外面调用的方法的事务被挂起
package maya.servicelmpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import maya.dao.IInfoDao; import maya.dao.IWorkDao; import maya.daolmpl.WorkDao; import maya.service.IInfoService; @Service public class InfoService implements IInfoService { @Autowired private IWorkDao workDao; @Autowired private IInfoDao infoDao; //使用自己的事务,外面调用的方法的事务被挂起,相当于TestAll.java中的事务失效 @Transactional(propagation=Propagation.REQUIRES_NEW) @Override public void delete(String code) { workDao.deleteByInfoCode(code); infoDao.delete(code); } }
运行结果(由于TestAll.java中的事务失效):“p008”已被删除,”p009“还存在