Spring10 事务

 实现的效果是:  用户在购买股票的时候,钱减少!股票增加!

 模拟出现的问题是!  用户在购买股票的时候,钱减少! 股票没有增加!

01.创建对应的数据库

02.创建对应实体类

复制代码
public class Account {  //银行账户
    private  Integer  aid;
    private  double  money;
    private  String  aname;
    public Integer getAid() {
        return aid;
    }
    public void setAid(Integer aid) {
        this.aid = aid;
    }
    public double getMoney() {
        return money;
    }
    public void setMoney(double money) {
        this.money = money;
    }
    public String getAname() {
        return aname;
    }
    public void setAname(String aname) {
        this.aname = aname;
    }
    public Account(Integer aid, double money, String aname) {
        super();
        this.aid = aid;
        this.money = money;
        this.aname = aname;
    }
    @Override
    public String toString() {
        return "Account [aid=" + aid + ", money=" + money + ", aname=" + aname
                + "]";
    }
    
    

}
复制代码
复制代码
public class Stock {  //股票
    
    private Integer sid;
    private Integer amount;
    private String sname;
    public Integer getSid() {
        return sid;
    }
    public void setSid(Integer sid) {
        this.sid = sid;
    }
    public Integer getAmount() {
        return amount;
    }
    public void setAmount(Integer amount) {
        this.amount = amount;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public Stock(Integer sid, Integer amount, String sname) {
        super();
        this.sid = sid;
        this.amount = amount;
        this.sname = sname;
    }
    public Stock() {
        super();
    }
    @Override
    public String toString() {
        return "Stock [sid=" + sid + ", amount=" + amount + ", sname=" + sname
                + "]";
    }
    
}
复制代码

03.创建对应的dao

复制代码
public interface StockDao {

      //股票开户
      void openStock(String sName,Integer amount);
      
      //增加股票
      void updateStock(String sName,Integer amount);
}
复制代码
复制代码
public interface AccoutDao {
    
      //银行开户
      void openAccount(String aName,double money);
      
      //购买股票
      void updateAccount(String aName,double money);

}
复制代码

04.创建对应的service和自定义的异常类

复制代码
public interface StockService {

      //股票开户
      void openStock(String sName,Integer amount);
      //银行开户
      void openAccount(String aName,double money);
    
      /**
       * 谁花了多少钱  买了 多少股票??
       */
      void  buyStock(String name,double money,Integer amount)  throws BuyStockException;
    
}
复制代码
复制代码
/**
 * @Transactional
 *  isolation:事务的隔离级别
 *  propagation:事务的传播行为
 *  rollbackFor :需要回滚的异常类!  类型是Class
 *  readOnly:对数据库的操作 只读!  默认false!
 *  timeout:设置与数据库连接的超时时间!  单位是S!  默认值  -1!
 */
public class StockServiceImpl implements StockService {
    
  private  StockDao  stockDao;
  private  AccoutDao  accountDao;
    
    //股票开户
  @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
    @Override
    public void openStock(String sName, Integer amount) {
        stockDao.openStock(sName, amount);
    }

    //银行开户
  @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
    @Override
    public void openAccount(String aName, double money) {
         accountDao.openAccount(aName, money);
     }

    /**
       * 谁花了多少钱  买了 多少股票??
       * 
       * 01.减钱
       * 02.加股
     * @throws BuyStockException 
       */
  @Transactional(rollbackFor=BuyStockException.class,isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
    @Override
    public void buyStock(String name, double money, Integer amount) throws BuyStockException {
        //银行账户减钱
        accountDao.updateAccount(name, money);
            if(1==1){  //模拟异常
                throw new BuyStockException("!!!购买股票失败.......");
            }
        stockDao.updateStock(name, amount);
    }

    
    
    public StockDao getStockDao() {
        return stockDao;
    }

    public void setStockDao(StockDao stockDao) {
        this.stockDao = stockDao;
    }

    public AccoutDao getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccoutDao accountDao) {
        this.accountDao = accountDao;
    }
    

}
复制代码
复制代码
/**
 * 自定义异常类
 */
public class BuyStockException extends Exception {

    public BuyStockException(String msg){
        super(msg);
    }
}
复制代码

05.创建applicationContext.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:c="http://www.springframework.org/schema/c"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        ">
      
    <!--  01.spring默认的数据源 
    <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring"/>
        <property name="username" value="t11"/>
        <property name="password" value="t11"/>
    </bean> -->  
    
    <!-- 02.dbcp数据源 
      <bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring"/>
        <property name="username" value="t11"/>
        <property name="password" value="t11"/>
    </bean>-->
    <!-- 加载配置文件  数据库需要的4要素 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <!-- 03.c3p0数据源  -->
       <bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.userName}"/>
        <property name="password" value="${jdbc.password}"/>
      </bean>
    
      
    <!-- 配置stockDao  -->  
    <bean id="stockDao" class="cn.bdqn.dao.impl.StockDaoImpl" p:dataSource-ref="dataSource"/>  
   <!-- 配置accountDao  -->
    <bean id="accountDao" class="cn.bdqn.dao.impl.AccountDaoImpl" p:dataSource-ref="dataSource"/>  
      
  <!--  配置stockService --> 
  <bean id="stockService" class="cn.bdqn.service.impl.StockServiceImpl" 
  p:accountDao-ref="accountDao"  p:stockDao-ref="stockDao"/>   
      
   <!-- ==================================事务的配置=========================================-->
    <!-- 配置事务管理器  -->  
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="dataSource"></property>
     </bean>
    
        <!-- 03.使用注解管理事务  -->
      <tx:annotation-driven transaction-manager="transactionManager"/>
    
      <!-- 01.使用代理工厂管理事务 -->
   <!--    <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
           <property name="transactionManager" ref="transactionManager"/>绑定事务管理器
           <property name="target" ref="stockService"/>  声明需要代理的bean 
            <property name="transactionAttributes">
               <props>在指定的切入点上配置事务属性
                  <prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
                   -:发生异常回滚     +:发生异常提交 
                  <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException</prop>
               </props>
            </property>
      </bean> -->
      
      <!-- 02.使用AspectJ来管理事务
       切入点的匹配表达式
        public  *  addStock(Stock stock) : * 代表匹配所有的返回值类型
        public  void *(Stock stock) :      * 代表匹配所有没有返回值的方法
        public  void addStock(..) :        .. 匹配所有的参数以及类型
        * cn.bdqn.service.*.*(..) :       匹配cn.bdqn.service包下所有类的所有方法
        * cn.bdqn.service..*(..) :        匹配cn.bdqn.service包以及子包下所有类的所有方法
        * *..service.*.*(..) :            匹配包名有service的包下所有类的所有方法              !!常用!!
      -->
         
<!--          <tx:advice id="txAdvice" transaction-manager="transactionManager">绑定事务管理器
             在连接点的方法上进行事务的属性配置
            <tx:attributes>
               <tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED"/>
               <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="BuyStockException"/>
            </tx:attributes>
         </tx:advice>
      
       指定切入点 
       <aop:config>
           <aop:pointcut expression="execution(* *..service.*.*(..))" id="myPoint"/>
           <aop:advisor advice-ref="txAdvice"  pointcut-ref="myPoint"/>
       </aop:config> -->
      
      
  
      
      
        
</beans>
复制代码

06.创建对应的测试类

复制代码
public class StockTest {

    public static void main(String[] args) throws BuyStockException {

        ApplicationContext context  =new  ClassPathXmlApplicationContext("applicationContext.xml");
        StockService service=(StockService) context.getBean("stockService");
        //service.openAccount("小猪", 5000);service.openStock("小猪", 20);
        service.buyStock("小猪", 250, 1);
    }
    
    
    
    // 01.使用代理工厂 管理事务
    @Test
    public  void  testProxy() throws BuyStockException{
        ApplicationContext context  =new  ClassPathXmlApplicationContext("applicationContext.xml");
        StockService service=(StockService) context.getBean("serviceProxy");
        service.buyStock("小猪", 250, 1);
    }
    
    // 02.使用AspectJ   和注解
    @Test
    public  void  testAop() throws BuyStockException{
        ApplicationContext context  =new  ClassPathXmlApplicationContext("applicationContext.xml");
        StockService service=(StockService) context.getBean("stockService");
        service.buyStock("小猪", 250, 1);
    }
    

}
复制代码
复制代码
public class ReadeMe {
    /**
     *   事务:一个或者一组sql语句来完成一个功能!
     *   事务具有的四个特性:  ACID特性!
     *   01.原子性:一个事物都是一个不可分割的单位!所有的操作 要么都执行,要么都不执行!
     *   02.一致性:事务必须是数据库从一个一致性的状态到达另一个一致性的状态!
     *   03.隔离性:一个事务的执行不会被其他的事务干扰!事务之间相互独立!
     *   04.持久性:事务一旦被提交!这个操作对数据库来说是永久性的!
     * 
     * 
     *  Spring的事务管理:
     *    事务本事是数据库中的概念! 按理说应该在数据访问层(dao)!
     *   
     *   绝大多数的情况下,我们是把事务 提升到  业务逻辑层!
     *   01.使用spring的事务代理工厂 来 管理事务!
     *   02.使用spring的注解                来 管理事务!     常用 
     *   03.使用AspectJ的AOP配置     来 管理事务!      常用
     *   
     *   需要掌握的两个属性名:
     *   
     *   isolation:事务的隔离级别!
     *    01.default:采用数据库默认的事务隔离级别
     *        001.mysql ---》repeatable-read
     *        002.oracle---》read_committed
     *    02. repeatable-read:可重复读取!解决了脏读,不可重复读,没解决幻读!
     *    03. read_committed:读已提交! 解决了脏读,没解决不可重复读,幻读!
     *    04. read_uncommitted:读未提交!什么都没有解决!
     *    05. serializable:串行化!级别最高!效率最低!不存在并发的问题!
     *   
     *   
     *   propagation: 事务的传播行为:一共7中方式!
     *    01.required:是spring默认的事务传播行为!
     *           指定的方法必须在事务中执行!如果没有事务,则会自动创建一个事务!
     *    02.supports:有事务就在事务环境下执行,没有事务就直接执行! 
     *    03.mandatory:
     *           指定的方法必须在事务中执行!如果没有事务,则抛出异常!
     *    04.requires_new:总是新创建一个事务!
     *       如果当前方法存在事务,则把当前的事务挂起,直到新创建的事务执行完毕后执行!
     *    05.not_supported:指定的方法不能在事务中执行!如果当前方法存在事务,则把当前的事务挂起!
     *    06.never:指定的方法不能在事务中执行!如果当前方法存在事务,则抛出异常!
     *    07.nested:指定的方法必须在事务内执行!
     *        如果执行的方法没有事务,则会创建一个事务!
     *        如果执行的方法没有事务,则会嵌套执行!
     *   
     *    timeout_default:定义了事务默认的超时时间!
     *   
     * 
     *   Spring事务管理的接口:PlatformTransactionManager
     *     常用的两个实现类:
     *     01.使用jdbc和MyBatis时     使用DataSourceTrancationManager
     *     02.使用hibernate时              使用HibernateTrancationManager
     *   
     *   Spring事务回滚的方式:
     *     默认的回滚方式--》发生运行时异常回滚!发送受查异常时提交!
     *     受查异常肯定需要我们手动的设置回滚方式!
     *     运行时异常严重!一旦发生,JVM中止执行!
     *     
     *    实现自定义异常类!RuntimeException -->  Exception --->  Throwable
     * 
     */
}
复制代码
原文地址:https://www.cnblogs.com/kaisadadi/p/7641033.html