Spring学习四(Spring事务管理)

来源:互联网 发布:imap使用的tcp端口是 编辑:程序博客网 时间:2024/05/11 15:16

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;@Transactionalpublic 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
原创粉丝点击