一、关于是事务
以方法为单位,进行事务控制;抛出异常,事务回滚。
最小的执行单位为方法。决定执行成败是通过是否抛出异常来判断的,抛出异常即执行失败
二、声明式事务:
声明式事务(declarative transaction management)是Spring提供的对程序事务管理的方式之一。
Spring的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明。用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。这样的好处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可;在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便。
Spring使用AOP来完成声明式的事务管理,因而声明式事务是以方法为单位,Spring的事务属性自然就在于描述事务应用至方法上的策略,在Spring中事务属性有以下四个参数:
1.传播行为
2.隔离级别
3.只读提示
4.事务超时期间
三、案例:编程实现购买股票的业务
1.编写实体类
2.编写dao层接口和实现
3.编写service层接口和实现
public class StockServiceImpl implements IStockService{ private IStockDao stockDao; private IAccountDao accountDao; public void setStockDao(IStockDao stockDao) { this.stockDao = stockDao; } public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } @Override public void buyStock(int sid, double scount, int aid, double abalance) { boolean isBuy = true; stockDao.updateStock(sid,scount,isBuy); accountDao.updateAccount(aid,abalance,isBuy); } @Override public void sellStock(int sid, double scount, int aid, double abalance) { boolean isBuy = false; stockDao.updateStock(sid,scount,isBuy); accountDao.updateAccount(aid,abalance,isBuy); } }
4.编写applicationContext.xml引入架包
(1)没有加入事务的xml文件
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="database.properties"/> </bean> <!--配置jdbc数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"></property> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--注册jdbcTemplate--> <bean id="jbdcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!--注册dao实现--> <bean id="accountDao" class="cn.bank.dao.impl.AccountDaoImpl"> <property name="jdbcTemplate" ref="jbdcTemplate"/> </bean> <bean id="stockDao" class="cn.bank.dao.impl.StockDaoImpl"> <property name="jdbcTemplate" ref="jbdcTemplate"/> </bean> <!--注册service实现--> <bean id="stockService" class="cn.bank.service.impl.StockServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="stockDao" ref="stockDao"/> </bean>
功能测试:
@Test public void buyStock(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); IStockService stockService = (IStockService) context.getBean("stockService"); stockService.buyStock(1001,1000,1204,10000); }
(此处没有关联股票价格)
(2)加入异常测试
@Override
public void buyStock(int sid, double scount, int aid, double abalance) {
boolean isBuy = true;
stockDao.updateStock(sid,scount,isBuy);
if (1==1) {
int i = 5 / 0;
}
accountDao.updateAccount(aid,abalance,isBuy);
}
报错:
处理结果:
在执行一次:
现在我们可以看到,在增加股票和减少余额中间产生异常之后,股票增加而余额没有减少,这种现在肯定是错误的。
(3)添加事务管理
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--通过bean元素生命需要Spring创建的实例。该实例的类型通过class属性指定, 并通过id属性为该实例制定一个名称,以便于访问--> <!--引入数据库配置文件--> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="database.properties"/> </bean> <!--配置jdbc数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"></property> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--注册jdbcTemplate--> <bean id="jbdcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!--注册dao实现--> <bean id="accountDao" class="cn.bank.dao.impl.AccountDaoImpl"> <property name="jdbcTemplate" ref="jbdcTemplate"/> </bean> <bean id="stockDao" class="cn.bank.dao.impl.StockDaoImpl"> <property name="jdbcTemplate" ref="jbdcTemplate"/> </bean> <!--注册service实现--> <bean id="stockService" class="cn.bank.service.impl.StockServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="stockDao" ref="stockDao"/> </bean> <!--引入事务平台管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--事务拦截处理:使用代理工厂--> <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="target" ref="stockService"/> <property name="transactionManager" ref="transactionManager"/> <!--事务参数的设定--> <property name="transactionAttributes"> <props> <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans>
测试(修改getBean()方法的参数):
@Test public void buyStockTest(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); IStockService stockService = (IStockService) context.getBean("serviceProxy"); stockService.buyStock(1001,1000,1204,10000); }
异常发生,数据没有改变(是我们预期的结果,也是业务需要的):
最后,去掉异常,保证事务管理下业务功能正常:
四:业务实现正常