spring 事务开发

  一、事务的ACID特性

  原子性atomicity:确保动作要不全部完成要么完全不起作用

  一致性consistency:数据和资源处于一种满足业务规则的一致性状态中

  隔离性isolation:用户的操作不能混淆

  持久性durability:一旦事务完成,无论发生什么系统错误,他的结果都不应该受影响

 二、事务的分类

  1、编程式事务(DAO实现)

package com.zzxtit.spring.tx.anno;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class StuCardDaoImpl implements StuCardDao{    
    @Autowired
    private JdbcTemplate jt;    
    /**
     * 根据学生卡编号查询学生卡信息
     */
    @Override
    public void updateStuCardByCardNo(StuCard sc) {
        // TODO Auto-generated method stub
        
        jt.update("update stu_card set money = ? where card_no = ?", sc.getMoney(), sc.getStuCardNo());
    }

    @Override
    public StuCard getStuCardInfoById(String cardNo) {
        // TODO Auto-generated method stub
        RowMapper<StuCard> rm = new BeanPropertyRowMapper<StuCard>();
        return jt.queryForObject("select card_no stuCardNo, money from stu_card where card_no = ?", rm, cardNo);
    }
    }
    /* public void payCard(){
     *             
     *         class.forname("");
     *         Connection conn=null;
     *        conn=driverManager.getConnection(url,user,password);
     *        Statement state=conn.creatStatement();
     *        conn.setAutoCommit(false);手动提交事务
     *         stat.executeUpdate(sql);把钱加在商户上
     *         stat.executeUpdate(sql);把钱从学生账户扣除
     *        if(扣钱失败){
     *             conn.rollback();回滚事务
     *         }else{
     *             conn.commit;提交事务
     *         }         
     * }
     * 

 

  初始化配置文件

  在IOC容器中声明transactionManager(事务管理器)

  编程式事务管理模板

       将管理模板注入到service里面

  开启事务

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        ">
  
      <context:component-scan base-package="com.zzxtit.spring.jdbc"></context:component-scan>
    <context:property-placeholder location="/springAOP/config/DB.properties"/>
    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${mysql_driver}"></property>
        <property name="url" value="${mysql_url}"></property>
        <property name="username" value="${mysql_username}"></property>
        <property name="password" value="${mysql_passwd}"></property>
    </bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" value="#{dataSource}"></property>
    </bean>
  
      <bean id="namedJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
          <constructor-arg index="0" ref="dataSource"></constructor-arg>
          <!-- 因为只有一个参数  所以不论用名字顺序都可以-->
      </bean>
     
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean> 
        
    <bean id="transcationTemplate" class="org.springframework.jdbc.core.namedParameterJdbcTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>
      
        <!-- name 是目标类里的属性值 -->
</beans>

 

  和事务相关的文件在program文件中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        ">
  
      <!-- 通过import标签引入其他上下文配置文件 -->
      <import resource="ApplicationContext-jdbc.xml"/>
     <bean id="stuCardDao" class="com.zzxtit.spring.tx.program.stuCardDaoImpl">
         <property name="jt" ref="jdbcTemplate"></property>
     </bean>   
     <bean id="stuCardService" class="com.zzxtit.spring.tx.program.StuCardServiceImpl">
         <property name="scDao" ref="stuCardDao"></property>
        <property name="transactionTemplate" ref="transcationTemplate"></property>
    
     </bean>  
</beans>

package com.zzxtit.spring.tx.program;
import java.math.BigDecimal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.zzxtit.spring.tx.exception.NoEnoughMoneyException;
import com.zzxtit.spring.tx.program.stuCard.StuCard;


public class StuCardServiceImpl implements stuCardService{

    private StuCard scDao;
    
    private TransactionTemplate transactionTemplate;
    
    /**
     *     转账支付,当金额不足时,抛出异常。
     * @param targetCardNo 目标账号
     * @param sourceCardNo 源账号
     * @param money 转账金额
     */
    
    //匿名内部类引用外部对象时需要定义成final类型的
         public void transaferMoney(final String targetCardNo, final String sourceCardNo, final String money) {
        
        transactionTemplate.execute(new TransactionCallback() {

            public Object doInTransaction(TransactionStatus status) {
                
                
                  StuCard sourceCard = scDao.getStuCardInfoById(sourceCardNo);
                  
                  
                  StuCard targetCard = scDao.getStuCardInfoById(targetCardNo); //修改后勤人员信息
                  sourceCard.setMoney(sourceCard.getMoney().subtract(new BigDecimal(money)));
                  
                  targetCard.setMoney(targetCard.getMoney().add(new BigDecimal(money)));
                  scDao.updateStuCardByCardNo(targetCard);
                  if(sourceCard.getMoney().compareTo(new BigDecimal("0")) < 0){ throw new
                  NoEnoughMoneyException("账户余额不足,请充值。。。。"); }
                  scDao.updateStuCardByCardNo(sourceCard);
                  System.out.println("支付完成!商品购买成功!!!!!");
                 
                
                return null;
            }
            
        });
        
        
    }

 

    2、声明式事务(XML 配置的方式  )

  初始化配置文件 加入命名空间

  加入事务的传播属性

  配置切入点  (作用在那些类上面) 作用在哪些方法上

  配置transactionManager事务作用在哪个管理器上面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/aop/spring-tx.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        ">
  
      <!-- 通过import标签引入其他上下文配置文件 -->
      <import resource="ApplicationContext-jdbc.xml"/>
     <bean id="stuCardDao" class="com.zzxtit.spring.tx.xml.stuCardDaoImpl">
         <property name="jt" ref="jdbcTemplate"></property>
     </bean>   
     <bean id="stuCardService" class="com.zzxtit.spring.tx.xml.StuCardServiceImpl">
         <property name="scDao" ref="stuCardDao"></property>
     </bean>  
     
     <!-- 事务的传播属性的配置 -->
     <!-- jdbc里的管理器管理,此时的传播属性为以下   -->
     <tx:advice id="txAdvice" transaction-manager="transactionManager">
             <tx:attributes>
                 <tx:method name="insert*" propagation="REQUIRED"/>
                 <tx:method name="add*" propagation="REQUIRED"/>
                 <tx:method name="update*" propagation="REQUIRED"></tx:method>
                 <tx:method name="modify*" propagation="REQUIRED"></tx:method>
                 <tx:method name="edit*" propagation="REQUIRED"></tx:method>
                 <tx:method name="delet*" propagation="REQUIRED"></tx:method>
                 <tx:method name="transfer*" propagation="REQUIRED"></tx:method>
                 
                 <tx:method name="query*" propagation="REQUIRED" read-only="true"></tx:method>
                 <tx:method name="select*" propagation="REQUIRED" read-only="true"></tx:method>
                 <tx:method name="find*" propagation="REQUIRED" read-only="true"></tx:method>        
                 
             </tx:attributes>         
     </tx:advice>
     
     <aop:config>
             <aop:pointcut expression="execution(* com.zzxtit.spring.*.xml.*.*(..))" id="txPointcut"/>
                                            <!-- * com.zzxtit.spring.*.service.*.*(..)) -->
             <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>                               
     </aop:config>     
</beans>
package com.zzxtit.spring.tx.xml;

import java.math.BigDecimal;

import com.zzxtit.spring.tx.exception.NoEnoughMoneyException;


public class StuCardServiceImpl implements StuCardService {

    private StuCardDao scDao;

    /**
     * 转账支付,当金额不足时,抛出异常。
     * 
     * @param targetCardNo 目标账号
     * @param sourceCardNo 源账号
     * @param money        转账金额
     */
    public void transaferMoney(String targetCardNo, String sourceCardNo, String money) {

        StuCard sourceCard = scDao.getStuCardInfoById(sourceCardNo);
        StuCard targetCard = scDao.getStuCardInfoById(targetCardNo);
        // 修改后勤人员信息
        sourceCard.setMoney(sourceCard.getMoney().subtract(new BigDecimal(money)));

        targetCard.setMoney(targetCard.getMoney().add(new BigDecimal(money)));
        scDao.updateStuCardByCardNo(targetCard);
        if (sourceCard.getMoney().compareTo(new BigDecimal("0")) < 0) {
            throw new NoEnoughMoneyException("账户余额不足,请充值。。。。");
        }
        scDao.updateStuCardByCardNo(sourceCard);
        System.out.println("支付完成!商品购买成功!!!!!");

    }

    /**
     * @return the scDao
     */
    public StuCardDao getScDao() {
        return scDao;
    }

    /**
     * @param scDao the scDao to set
     */
    public void setScDao(StuCardDao scDao) {
        this.scDao = scDao;
    }

}

 

    3、  声明式事务(注解式)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/context/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        ">
  
    <!-- 通过import标签引入其他上下文配置文件 -->
      <import resource="ApplicationContext-jdbc.xml"/>
      
      <context:component-scan base-package="com.zzxtit.spring.*.anno"></context:component-scan>
      
      <tx:annotation-driven transaction-manager="transactionManager"/>
  
         
</beans>

 

@Repository
public class StuCardDaoImpl implements StuCardDao{    
    @Autowired
    private JdbcTemplate jt;    
    /**
     * 根据学生卡编号查询学生卡信息
     */
    @Override
    public void updateStuCardByCardNo(StuCard sc) {
        // TODO Auto-generated method stub
        
        jt.update("update stu_card set money = ? where card_no = ?", sc.getMoney(), sc.getStuCardNo());
    }

    @Override
    public StuCard getStuCardInfoById(String cardNo) {
        // TODO Auto-generated method stub
        RowMapper<StuCard> rm = new BeanPropertyRowMapper<StuCard>();
        return jt.queryForObject("select card_no stuCardNo, money from stu_card where card_no = ?", rm, cardNo);
    }
}

 

package com.zzxtit.spring.tx.anno;
import java.math.BigDecimal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.zzxtit.spring.tx.exception.NoEnoughMoneyException;


@Service
public class StuCardServiceImpl implements StuCardService {

    @Autowired
    private StuCardDao scDao;

    /**
     * 转账支付,当金额不足时,抛出异常。
     * 
     * @param targetCardNo 目标账号
     * @param sourceCardNo 源账号
     * @param money        转账金额
     */
     @Transactional(propagation=Propagation.REQUIRED, timeout=5 )
    public void transaferMoney(String targetCardNo, String sourceCardNo, String money) {

        StuCard sourceCard = scDao.getStuCardInfoById(sourceCardNo);
        StuCard targetCard = scDao.getStuCardInfoById(targetCardNo);
        // 修改后勤人员信息
        sourceCard.setMoney(sourceCard.getMoney().subtract(new BigDecimal(money)));

        targetCard.setMoney(targetCard.getMoney().add(new BigDecimal(money)));
        scDao.updateStuCardByCardNo(targetCard);
        if (sourceCard.getMoney().compareTo(new BigDecimal("0")) < 0) {
            throw new NoEnoughMoneyException("账户余额不足,请充值。。。。");
        }
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }  //超时设置
        scDao.updateStuCardByCardNo(sourceCard);
        System.out.println("支付完成!商品购买成功!!!!!");
        
    }

}

 

 

 

 

 

 

  事务的传播行为:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
  

 

三、spring具名参数

  将named parameterjdbc配置到spring  ioc容器里面

    <bean id="namedJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
          <constructor-arg index="0" ref="dataSource"></constructor-arg>
          <!-- 因为只有一个参数  所以不论用名字顺序都可以-->
      </bean>

  将属性注入到dao里面 

(或者用反射将属性的值映射成一个map)

    private NamedParameterJdbcTemplate npjTemplate;
        
        pubilc void insterUserInfoByNJP(SysUserInfo su) {
            String sql="insert into t_sys_user (user_name, passwd, salt, real_name, avatar, phone, email, gender, create_time) "
                    + "values (userName:, passwd:, salt:, realName:, avatar:, phone:,email:, gender:, now())";
            
            Map<String,Object> paramMap=new HashMap<String,Object>();
            paramMap.put("username", su.getUserName());
            
            npjTemplate.update(sql, paramMap);
        }
    }

 

  当需要注入很多字段时使用具名函数

 

    ctrl shift R找类 输入类名 找src里的类

    ctrl shift T 找jar包里的类

 

 

 

 

 

 

 

 

 

posted @ 2019-11-25 10:33  jkkkkkk  阅读(156)  评论(0)    收藏  举报