SSM-Spring-21:Spring中事物的使用案例
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------
股票买卖案例(我会用三种开启事物的方法 代理工厂bean版的,注解版的,aspectj xml版的)
简单的介绍一下这个小例子,就是俩个表,一个就是你的账户表,一张就是你的股票的表
一切从简,写的简单一点(你可以看成有很多不严谨的地方,只是一个Spring中的事务的简单使用,仅供理解事务,不用想太多)
之前的那些jar包就不说了,从案例开始
01.数据库准备:
01.1账户表Account
01.2股票表Stock
02.IDEA中分层开发:
02.1实体类(前面俩个实体类可以说在这个例子里没有用到,但是这是一种习惯)
StockInfo表
package cn.dawn.day22tx.entity; /** * Created by Dawn on 2018/3/15. */ public class StockInfo { 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; } }
AccountInfo表
package cn.dawn.day22tx.entity; /** * Created by Dawn on 2018/3/15. */ public class AccountInfo { private Integer aid; private String aname; private Integer ablance; 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 Integer getAblance() { return ablance; } public void setAblance(Integer ablance) { this.ablance = ablance; } }
StockException类
package cn.dawn.day22tx.entity; /** * Created by Dawn on 2018/3/15. */ public class StockException extends ClassNotFoundException { public StockException() { } public StockException(String s) { super(s); } }
这个类有点要说的,Spring的事务中执行一半遇到异常怎么操作?默认情况下是运行异常会回滚/受查异常会提交这执行过的代码,所以我做了个受查异常,一会可以测试一下
02.2dao层,一个对股票表操作,一个对账户表操作
IStockDAO股票接口
package cn.dawn.day22tx.dao; /** * Created by Dawn on 2018/3/15. */ public interface IStockDAO { public boolean updateStock(int sid,int scount,boolean isBuy); }
StockDAOImpl股票接口的实现类
package cn.dawn.day22tx.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * Created by Dawn on 2018/3/15. */ public class StockDAOImpl extends JdbcDaoSupport implements IStockDAO { public boolean updateStock(int sid, int scount, boolean isBuy) { String sql=""; boolean flag=false; if (isBuy){ //买股票 sql="update stock set scount=scount+? where sid=?"; }else { sql="update stock set scount=scount-? where sid=?"; } int result = this.getJdbcTemplate().update(sql,scount,sid); if (result>0) { flag = true; } return flag; } }
这儿我将isBuy的布尔变量当等于true的时候,进行买股票操作,你的股票表上的股票股数增加
IAccountDAO账户接口
package cn.dawn.day22tx.dao; /** * Created by Dawn on 2018/3/15. */ public interface IAccountDAO { public boolean updateAccount(int aid,int ablance,boolean isBuy); }
AccountDAOImpl账户的实现类
package cn.dawn.day22tx.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * Created by Dawn on 2018/3/15. */ public class AccountDAOImpl extends JdbcDaoSupport implements IAccountDAO { public boolean updateAccount(int aid, int ablance, boolean isBuy) { String sql=""; boolean flag=false; if(isBuy){ //买股票 sql="update account set ablance=ablance-? where aid=?"; }else { sql="update account set ablance=ablance+? where aid=?"; } int count = this.getJdbcTemplate().update(sql, ablance, aid); if(count>0){ flag=true; } return flag; } }
02.3service层
股票的交易接口IStockPayService
package cn.dawn.day22tx.service; import cn.dawn.day22tx.entity.StockException; /** * Created by Dawn on 2018/3/15. */ public interface IStockPayService { public boolean buyStock(int aid,int ablance,int sid,int scount) throws StockException; }
股票交易的实现类StockPayServiceImpl
package cn.dawn.day22tx.service; import cn.dawn.day22tx.dao.IAccountDAO; import cn.dawn.day22tx.dao.IStockDAO; import cn.dawn.day22tx.entity.StockException; import org.springframework.transaction.annotation.Transactional; /** * Created by Dawn on 2018/3/15. */ public class StockPayServiceImpl implements IStockPayService { IStockDAO iStockDAO; IAccountDAO iAccountDAO; //@Transactional(rollbackFor = StockException.class) public boolean buyStock(int aid, int ablance, int sid, int scount) throws StockException { boolean isBuy=true; boolean sflag = iStockDAO.updateStock(sid, scount, isBuy); if(true){ throw new StockException("网络被挂掉异常"); } boolean aflag = iAccountDAO.updateAccount(aid, ablance, isBuy); if(sflag&&aflag) return true; else return false; } public IStockDAO getiStockDAO() { return iStockDAO; } public void setiStockDAO(IStockDAO iStockDAO) { this.iStockDAO = iStockDAO; } public IAccountDAO getiAccountDAO() { return iAccountDAO; } public void setiAccountDAO(IAccountDAO iAccountDAO) { this.iAccountDAO = iAccountDAO; } }
看到那个方法上面注释掉的那个注解了吗?那是第二种方式要用到,只有在第二种方式注解版的时候才用到,其他俩种方式就注释掉它,免得有干扰,切记,用的时候把注释消掉,不用就注释它
@Transactional里面我只写了遇到什么异常会回滚,它的传播行为和隔离级别有默认值,我就省略了
03.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:aop="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop.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"> <!--配置jdbc。properties--> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!--阿里的Druid--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--dao层--> <bean id="stockDAO" class="cn.dawn.day22tx.dao.StockDAOImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="accountDAO" class="cn.dawn.day22tx.dao.AccountDAOImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!--service--> <bean id="stockpPayService" class="cn.dawn.day22tx.service.StockPayServiceImpl"> <property name="iAccountDAO" ref="accountDAO"></property> <property name="iStockDAO" ref="stockDAO"></property> </bean> <!--事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--第三种方式 aspectj xml版--> <tx:advice id="txadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="mypointccut" expression="execution(* *..day22tx.service.*.*(..))"></aop:pointcut> <aop:advisor advice-ref="txadvice" pointcut-ref="mypointccut"></aop:advisor> </aop:config> <!--第二种事务开启方式,注解版--> <!--<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>--> <!--第一种事务开启方式代理工厂--> <!--<bean id="txService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"></property> <property name="target" ref="stockpPayService"></property> <property name="transactionAttributes"> <props> <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-StockException</prop> </props> </property> </bean>--> </beans>
没什么需要说的,这儿像什么命名空间等需要注意一点,其他的就是照猫画虎
有什么不清楚的评论留言,我会帮忙解决
04.单测方法:
package cn.dawn.day22tx; import cn.dawn.day22tx.entity.StockException; import cn.dawn.day22tx.service.IStockPayService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; /** * Created by Dawn on 2018/3/3. */ public class test20180315 { @Test /*aspectj xml方式*/ public void t03() { ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-day22tx.xml"); IStockPayService service = (IStockPayService) context.getBean("stockpPayService"); boolean flag = false; try { flag = service.buyStock(1, 100, 1, 20); } catch (StockException e) { e.printStackTrace(); } if(flag){ System.out.println("购买成功"); } } @Test /*注解方式*/ public void t02() { ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-day22tx.xml"); IStockPayService service = (IStockPayService) context.getBean("stockpPayService"); boolean flag = false; try { flag = service.buyStock(1, 100, 1, 20); } catch (StockException e) { e.printStackTrace(); } if(flag){ System.out.println("购买成功"); } } @Test /*代理工厂bean的方式*/ public void t01() { ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-day22tx.xml"); IStockPayService service = (IStockPayService) context.getBean("txService"); boolean flag = false; try { flag = service.buyStock(1, 100, 1, 20); } catch (StockException e) { e.printStackTrace(); } if(flag){ System.out.println("购买成功"); } } }
简述一下运行结果,单测成功,中途会打印异常信息,由于开启了事务,同生共死,俩张表在数据库都没有改变值,事务的出口被回滚了