一、事务概述

1、什么是事务

事务管理是企业级应用程序开发中必不可少的技术,用啦I确保数据的完整性和一致性
事务就是一系列的动作,它们被党作用一个简单的工作单元,这些动作要么全部完成,要么全部不起作用

事务的四大特征(ACID)

  • 原子性(Atomicity):是不可分割的最少操作单位,要么同时完成,要么同时失败
  • 一致性(Consistency):事务操作前后,保证数据的一致性
  • 隔离性(Isolation):多个事务之间,互相独立,互不干扰
  • 持久性(Durability):当事务提交或回滚后,数据库会持久化的保存数据

    编程式事务【了解】

    就是将业务代码和事务代码放在一起书写,它的耦合性太高,开发中不使用

    声明式事务

    其实就是将事务代码(spring内置)和业务代码隔离开发,然后通过一段配置让他们组装运行,最后达到事务控制的目的(原理:AOP)

    2、Spring事务管理器

    PlatformTransactionManager
    spring事务管理器的顶级接口,它为事务管理封装了一组独立于技术的方法,无论使用Spring的哪种事务管理策略(编程式或者声明式),事务管理器都是必须的

    1. <!--springorm-->
    2. <dependency>
    3. <groupId>org.springframework</groupId>
    4. <artifactId>spring-orm</artifactId>
    5. <version>5.1.5.RELEASE</version>
    6. </dependency>

    二、事务环境

    用于转账,要么同时成功,要么同时失败

    相关坐标:

    ```java

    mysql mysql-connector-java 5.1.47 com.alibaba druid 1.1.15 org.springframework spring-jdbc 5.1.5.RELEASE org.springframework spring-context 5.1.5.RELEASE junit junit 4.12 org.springframework spring-test 5.1.5.RELEASE
  1. <build>
  2. <plugins>
  3. <!-- 设置编译版本为1.8 -->
  4. <plugin>
  5. <groupId>org.apache.maven.plugins</groupId>
  6. <artifactId>maven-compiler-plugin</artifactId>
  7. <version>3.1</version>
  8. <configuration>
  9. <source>1.8</source>
  10. <target>1.8</target>
  11. <encoding>UTF-8</encoding>
  12. </configuration>
  13. </plugin>
  14. </plugins>
  15. </build>
  1. <a name="BZ2Hh"></a>
  2. #### 配置文件:
  3. ```java
  4. <beans xmlns="http://www.springframework.org/schema/beans"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  9. <!--开启注解扫描-->
  10. <context:component-scan base-package="com.itfxp"/>
  11. <!--引入jdbc.properties配置文件-->
  12. <context:property-placeholder location="classpath:jdbc.properties"/>
  13. <!--
  14. 配置Druid数据库连接池
  15. -->
  16. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  17. <property name="driverClassName" value="${jdbc.driverClassName}"></property>
  18. <property name="url" value="${jdbc.url}"></property>
  19. <property name="username" value="${jdbc.username}"></property>
  20. <property name="password" value="${jdbc.password}"></property>
  21. </bean>
  22. <!--
  23. 配置jdbcTemplate
  24. -->
  25. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  26. <property name="dataSource" ref="dataSource"></property>
  27. </bean>
  28. </beans>
  29. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  30. jdbc.driverClassName=com.mysql.jdbc.Driver
  31. jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=UTF-8
  32. jdbc.username=root
  33. jdbc.password=root
  34. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35. -- 创建数据表
  36. CREATE TABLE account ( -- 账户表
  37. id INT PRIMARY KEY AUTO_INCREMENT,
  38. `name` VARCHAR(32),
  39. money DOUBLE
  40. );
  41. -- 添加数据
  42. INSERT INTO account (`name`, money) VALUES ('蝴蝶姐', 1000), ('罗志祥', 1000);

Dao层:

  1. @Repository
  2. public class AccountDaoImpl implements AccountDao {
  3. // 依赖jdbcTemplate
  4. @Autowired
  5. private JdbcTemplate jdbcTemplate;
  6. @Override
  7. public void outUser(String outUser, Double money) {
  8. // 1.编写sql
  9. String sql = "update account set money = money - ? where name = ?";
  10. // 2.执行sql
  11. jdbcTemplate.update(sql, money,outUser);
  12. }
  13. @Override
  14. public void inUser(String inUser, Double money) {
  15. // 1.编写sql
  16. String sql = "update account set money = money + ? where name = ?";
  17. // 2.执行sql
  18. jdbcTemplate.update(sql, money,inUser);
  19. }
  20. }
  21. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  22. public interface AccountDao {
  23. /**
  24. * 转出操作
  25. * @param user 转出的账号
  26. * @param money 转出金额
  27. */
  28. void outUser(String user,Double money);
  29. /**
  30. * 转入操作
  31. * @param user 转入的账号
  32. * @param money 转入金额
  33. */
  34. void inUser(String user,Double money);
  35. }

serivice层:

  1. @Service
  2. public class AccountServiceImpl implements AccountService {
  3. @Autowired
  4. private AccountDao accountDao;
  5. @Override
  6. public void transfer(String outUser, String inUser, Double money) {
  7. // 核心业务
  8. accountDao.outUser(outUser, money);
  9. accountDao.inUser(inUser, money);
  10. }
  11. }
  12. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13. public interface AccountService {
  14. /**
  15. * 转账
  16. * @param outUser 转出用户
  17. * @param inUser 转入用户
  18. * @param money 金额
  19. */
  20. public void transfer(String outUser, String inUser, Double money);
  21. }

web层:

  1. /**
  2. * 将单元测试的运行器,切换为Spring的运行器
  3. */
  4. @RunWith(SpringRunner.class)
  5. /**
  6. * 加载配置文件
  7. */
  8. @ContextConfiguration("classpath:applicationContext.xml")
  9. public class SpringTransferTest {
  10. @Autowired
  11. private AccountService accountService;
  12. @Test
  13. public void test01() {
  14. accountService.transfer("罗志祥","蝴蝶姐",500.0);
  15. }
  16. }

三、Spring编程式事务

1、配置事务管理器

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

2、事务的模板(作用于service层)

  1. @Service
  2. public class xxxServiceImpl implements xxxService{
  3. @Autowired
  4. private PlatformTransactionManager transactionManager;
  5. public void method() {
  6. DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  7. // 设置是否只读,为false才支持事务
  8. def.setReadOnly(false);
  9. // 设置隔离级别
  10. def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
  11. // 设置事务的传播行为
  12. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  13. // 对事务管理器进行配置
  14. TransactionStatus status = transactionManager.getTransaction(def);
  15. try {
  16. // 业务操作
  17. // ......................
  18. // 提交事务
  19. transactionManager.commit(status);
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. // 回滚事务
  23. transactionManager.rollback(status);
  24. }
  25. }
  26. }

四、Spring声明式事务

1、xml方式

导入坐标

  1. <!--springorm-->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-orm</artifactId>
  5. <version>5.1.5.RELEASE</version>
  6. </dependency>
  7. <!--aspectj-->
  8. <dependency>
  9. <groupId>org.aspectj</groupId>
  10. <artifactId>aspectjweaver</artifactId>
  11. <version>1.9.5</version>
  12. </dependency>

引入事务的约束

  1. xmlns:tx="http://www.springframework.org/schema/tx"
  2. http://www.springframework.org/schema/tx
  3. http://www.springframework.org/schema/tx/spring-tx.xsd

事务管理器

  1. <!--
  2. 定义事务管理器信息 DefaultTransactionDefinition
  3. 我们可以控制指定的方法,设置事务隔离级别、传播行为、是否只读、是否超时...
  4. name="transfer" 需要控制事务的方法名
  5. isolation="DEFAULT" 设置当前方法的事务隔离界别,mysql默认级别:repeatable_read
  6. propagation="REQUIRED" 设置当前方法的事务传播行为 REQUIRED:当前方法必须有一个事务(单独 使用开启,别人调用加入对方事务)
  7. read-only="false" 当前方式为非只读(增删改用的)
  8. timeout="-1" 事务超时时间,-1:永不超时
  9. -->
  10. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  11. <!--定义事务管理器信息-->
  12. <tx:attributes>
  13. //表示对所有的方法都进行事故管理
  14. <tx:method name="*"/>
  15. //具体划分
  16. <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
  17. <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
  18. <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
  19. <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
  20. <tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
  21. </tx:attributes>
  22. </tx:advice>
  23. <!--
  24. 配置aop
  25. -->
  26. <aop:config>
  27. <!--
  28. 此标签仅支持Spring事务管理器使用
  29. 通知+切点=切面
  30. -->
  31. <aop:advisor advice-ref="txAdvice"
  32. pointcut="execution(* com.itfxp.service..*.*(..))"></aop:advisor>
  33. </aop:config>

1、注解方式

开启事务注解

  1. <!--开启事务注解支持-->
  2. <tx:annotation-driven />

将@Transactional作用在方法上

  1. 用法同xml一样:
  2. @Transactional(
  3. isolation = Isolation.DEFAULT,
  4. propagation = Propagation.REQUIRED,
  5. readOnly = true,
  6. timeout = -1)

将@Transactional作用在方法上

当前类中的所有方法全部被事务管理