Spring学习四(Spring事务管理)

1、事务概念

事务是一组操作执行的单元,对于数据库来说,要么完全执行,要么完全不执行。通过一组相关操作组合为一个要么全部成功,要么全部失败的单元,可以简化错误回复并使应用程序更加可靠。
事务的ACID

  • Atomic(原子性):要么都发生,要么都不发生。
  • Consistent(一致性):事务执行前后,数据一致性。例如tom账户减去100,相应的jerry账户就多出100
  • Isolate(隔离性):当同时存在多个事务的时候,事务之间应该不收干扰。
  • Durable(持久性):永久保存,例如保存到数据库中等

脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。

不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。

幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。

数据库准备了以下隔离级别来规避以上问题的产生
这里写图片描述

2、Spring事务管理

Spring事务管理机制:三个核心组件
1、PlatformTransactionManager平台事务管理器

2、TransactionDefinition
- 事务定义信息和事务管理相关参数
- 隔离级别、传播级别
- 超时 、事务是否只读
3、TransactionStatus
事务运行过程中的动态信息,比如提交,回滚

一些数据库的默认隔离级别
大部分数据库设置隔离级别为Read Commited
SqlServer:Read Commited
Oracle:Read Commited
但是Mysql设置隔离级别:
Mysql:Repeatable_Read

3、事务的传播行为

这里写图片描述

4、Spring AOP注解实现事务

1、配置事务管理器,并把事务管理器交给spring事务注解驱动
2、在目标类上使用注解@Transactional

Demo示例:对于转账成功操作和非成功操作
这里写图片描述
1、数据库导入
这里写图片描述
代码

CREATE DATABASE spring;
USE spring;
CREATE TABLE Account(id INT,username VARCHAR(20),money INT);
INSERT INTO account(id,username,money)VALUES(1,'tom',1000);
INSERT INTO account(id,username,money)VALUES(2,'cat',1000);

2、dao,daoImpl

public interface AccountDao {
    void in(String inUser, int money);

    void out(String outUser, int money);
}
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

    public void in(String inUser, int money) {
        // TODO Auto-generated method stub
        this.getJdbcTemplate().update(
                "update account set money = money + ? where username = ?",
                money, inUser);
    }

    public void out(String outUser, int money) {
        // TODO Auto-generated method stub
        this.getJdbcTemplate().update(
                "update account set money = money - ? where username = ?",
                money, outUser);
    }

}

3、service,serviceImpl

public interface AccountService {
    public abstract void transfer(String outUser, String inUser, int money);
}
import org.springframework.transaction.annotation.Transactional;

import com.example.spring.dao.AccountDao;

@Transactional
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

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

    public void transfer(String outUser, String inUser, int money) {
        // TODO Auto-generated method stub
        accountDao.out(outUser, money);
        System.out.println("out money sucess");
         int i=1/0;
        accountDao.in(inUser, money);
        System.out.println("in money sucess");
    }

}

4、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:aop="http://www.springframework.org/schema/aop"
    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/tx 
                           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>
    <!-- 配置dao -->
    <bean id="accountDao" class="com.example.spring.dao.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置service -->
    <bean id="accountService" class="com.example.spring.service.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!-- # 配置事务管理器 -->
    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- #将事务管理配置给spring,交予事务注解驱动 -->
    <tx:annotation-driven transaction-manager="txManager" />


</beans>                           

5、测试代码

@Test
    public void testString() {
        String xmlPath = "applicationContext.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                xmlPath);
        AccountService accountService=(AccountService) applicationContext.getBean("accountService");
        accountService.transfer("tom", "cat", 100);

    }

经测试在异常情况下,转账操作正确无误。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值