spring 事务的运用

1.事务

  简介:通常事务是用来处理客户请求的一些操作, 更好的服务客户的请求,同时处理好并发事务,是学好处理事务的重点

  四个特点:原子性(要起作用就全起作用),

       隔离性(彼此事务互不影响),

          持久性(一旦生效不会改变),

          一致性(始终满足规定)。

  分类:编程式与声明式,即手动手动控制事物的开始提交回滚或spring自动控制。

  并发事务:即多个事务同时发生,则需要合理的处理以免发生混乱(脏读,不可重复读,幻读)

  事务隔离级别:即事务的多种规定操作类型范围(如下图)

ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是ISOLATION_READ_COMMITTED。
ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

 

          

 2.实战(是否使用注解)

  <1> 使用xml的配置实现

        

      实例化事务管理器(类似于DataSource)

    

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

      编程式事务,事务管理器模板

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

      可以通过在另个xml文件中通过import标签引入其他上下文配置

<import resource="applicationContext-jdbc.xml"/>

      将使用类加载进入

<bean id="stuCardDao" class="com.zzxtit.springboot.tx.program.StuCardDaoImpl">
        <property name="jt" ref="jdbcTemplate"></property>
</bean>

<bean id="stuCardService" class="com.zzxtit.springboot.tx.program.StuCardServiceImpl">
  <property name="scDao" ref="stuCardDao"></property>
  <property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>

 

     在servlet中继承一个接口实现他的方法,同时添加其get set方法

public void transaferMoney(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;
}
});
}

在Dao中完成数据库的操作

/**
     * 根据学生卡编号查询学生卡信息
     */
    public StuCard getStuCardInfoById(String cardNo) {
        RowMapper<StuCard> rm = new BeanPropertyRowMapper<StuCard>(StuCard.class);
        return jt.queryForObject("select card_no stuCardNo, money from stu_card where card_no = ?", rm, cardNo);
    }

    /**
     * 更新学生卡信息
     */
    public void updateStuCardByCardNo(StuCard sc) {
        jt.update("update stu_card set money = ? where card_no = ?", sc.getMoney(), sc.getStuCardNo());
    }

  在main函数中添加上spring容器即可使用,且满足事务特性,如余额不足不会扣钱和加钱。

public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("config/applicationContext-program.xml");
        
        StuCardService stuCardService = ioc.getBean(StuCardService.class);
        stuCardService.transaferMoney("123456", "12345", "100");
    }

    <2> 使用注解的配置实现

    同样需要把事务管理器和事务模板配置到jdbc.xml中

<!-- 
        实例化事务管理器
     -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 
        编程式事务 事务管理模板
     -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

 

使用tx标签引入自动事务处理

<tx:annotation-driven transaction-manager="transactionManager"/>

除了添加ioc的bean注解之外,通过@Transactional的注解来简便实现事务的自动处理

    在括号内可以声明事务的隔离级别 以及可以添加上超时事务处理等

@Transactional(propagation=Propagation.REQUIRED, timeout=5 )

 

  

    

posted @ 2019-11-23 16:36  河道蟹  阅读(258)  评论(0)    收藏  举报