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("购买成功");
        }

    }
}

  简述一下运行结果,单测成功,中途会打印异常信息,由于开启了事务,同生共死,俩张表在数据库都没有改变值,事务的出口被回滚了

 

posted @ 2018-03-15 19:07  晨曦Dawn  阅读(293)  评论(0编辑  收藏  举报