Spring 实现事务的三种方式
事务:保证数据的运行不会说A给B钱,A钱给了B却没收到。
实现事务的三种方式(重要代码):
1.aspectJ AOP实现事务:
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dateSource"></property>
</bean>
<tx:advice id="stockAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="by*" isolation="DEFAULT" propagation="REQUIRED" rollback-for="MyExepction"/>
<tx:method name="select*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="exAdvice" expression="execution(* *..service.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="stockAdvice" pointcut-ref="exAdvice"></aop:advisor>
</aop:config>
2.事务代理工厂Bean实现事务:
<bean id="tproxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="dataSourceTransactionManager"></property><!–写的是事务–>
<property name="target" ref="byStockService"></property><!–要进行事务的类–>
<property name="transactionAttributes">
<props><!–key写的是service层要增强的方法–>
<!– 事务的隔离级别,后面逗号后面是异常类,用于回滚数据–>
<prop key="ByStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-MyExepction</prop>
</props>
</property>
</bean>
3.注解方式实现事务:
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
在需要进行事务的方法上增加一个注解“@Transactional(rollbackFor = MyExepction.class )”
做一个买股票的小例子来看一下事务:
1.使用事务工厂Bean:
xml:
这个异常刚好卡在支付金额,和股票增加直接,
RuntimeException是运行时异常
Exception是检查异常
两者的区别:
运行时异常是默认回滚,
检查异常是默认提交的。
数据表:
结果异常出现后,数据进行了回滚,A表中并没有少余额,B表中也没有多股票。
基本的架构:
dao:
IStockDao:
package cn.Spring.Day20xy.dao; public interface IStockDao { public int updateStock(int sid,int soucnt,boolean isbuay)throws Exception; }
IAccountDao:
package cn.Spring.Day20xy.dao; public interface IAccountDao { public int updateAccount(int aid,Double amoeny,boolean isbay) throws Exception; }
StockDaoImpl:
package cn.Spring.Day20xy.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class StockDaoImpl extends JdbcDaoSupport implements IStockDao { @Override public int updateStock(int sid, int soucnt, boolean isbuay) throws Exception { String sql=""; if (isbuay){ sql="update stock set scount=scount+? where sid=?"; }else { sql="update stock set scount=scount-? where sid=?"; } return this.getJdbcTemplate().update(sql,soucnt,sid); } }
AccountDaoImpl:
package cn.Spring.Day20xy.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao{ @Override public int updateAccount(int aid,Double amoeny,boolean isbay) throws Exception { String sql=""; if (isbay){ sql="update account set abalance=abalance-? where aid=?"; }else { sql="update account set abalance=abalance+? where aid=?"; } return this.getJdbcTemplate().update(sql,amoeny,aid); } }
entity:
Account:
package cn.Spring.Day20xy.entity; public class Account { private Integer aid; private String aname; private double abalance; public Integer getAid() { return aid; } public void setAid(Integer aid) { this.aid = aid; } public String getAname() { return aname; } public void setAname(String aname) { this.aname = aname; } public double getAbalance() { return abalance; } public void setAbalance(double abalance) { this.abalance = abalance; } }
Stock:
package cn.Spring.Day20xy.entity; public class Stock { //股票代号 private Integer sid; //股票名称 private String sname; //股数 private Integer scount; public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Integer getScount() { return scount; } public void setScount(Integer scount) { this.scount = scount; } }
MyExepction:
package cn.Spring.Day20xy.entity; public class MyExepction extends RuntimeException { public MyExepction() { } public MyExepction(String message) { super(message); } }
service:
IByStockService :
package cn.Spring.Day20xy.service; public interface IByStockService { public int ByStock(int aid,double moeny,int sid ,int count)throws Exception; }
ByStockServiceImpl:
package cn.Spring.Day20xy.service; import cn.Spring.Day20xy.dao.IAccountDao; import cn.Spring.Day20xy.dao.IStockDao; import cn.Spring.Day20xy.entity.MyExepction; import org.springframework.transaction.annotation.Transactional; public class ByStockServiceImpl implements IByStockService{ //植入Dao private IAccountDao accountDao; private IStockDao stockDao; @Override @Transactional(rollbackFor = MyExepction.class ) public int ByStock(int aid,double moeny,int sid ,int count) throws Exception { boolean isbay=true; int i = accountDao.updateAccount(aid, moeny, isbay); if (1==1) { throw new MyExepction("出异常了"); } int i1 = stockDao.updateStock(sid, count, isbay); return i+i1; } public IAccountDao getAccountDao() { return accountDao; } public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } public IStockDao getStockDao() { return stockDao; } public void setStockDao(IStockDao stockDao) { this.stockDao = stockDao; } }
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:p="http://www.springframework.org/schema/p" 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.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--1.配置数据源--> <bean id="dateSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql:///newss2230"></property> <property name="username" value="root"></property> <property name="password" value="123"></property> </bean> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!--2.JDBCTampLate--> <bean id="jdbcTempLate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dateSource"></property> </bean> <!--3.Dao--> <bean id="accountDao" class="cn.Spring.Day20xy.dao.AccountDaoImpl"> <property name="jdbcTemplate" ref="jdbcTempLate"></property> </bean> <!--3.Dao--> <bean id="stockDao" class="cn.Spring.Day20xy.dao.StockDaoImpl"> <property name="jdbcTemplate" ref="jdbcTempLate"></property> </bean> <!--4.Service--> <bean id="byStockService" class="cn.Spring.Day20xy.service.ByStockServiceImpl"> <property name="accountDao" ref="accountDao"></property> <property name="stockDao" ref="stockDao"></property> <!--事务--> </bean> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dateSource"></property> </bean> <!--事务注解驱动--> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/> <!--事务代理工厂bean--> <!--<bean id="tproxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="dataSourceTransactionManager"></property> <property name="target" ref="byStockService"></property> <property name="transactionAttributes"> <props><!–key写的是service层的方法–> <prop key="ByStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-MyExepction</prop> </props> </property> </bean>--> </beans>