一、事务概述
1、什么是事务
事务管理是企业级应用程序开发中必不可少的技术,用啦I确保数据的完整性和一致性
事务就是一系列的动作,它们被党作用一个简单的工作单元,这些动作要么全部完成,要么全部不起作用
事务的四大特征(ACID)
- 原子性(Atomicity):是不可分割的最少操作单位,要么同时完成,要么同时失败
- 一致性(Consistency):事务操作前后,保证数据的一致性
- 隔离性(Isolation):多个事务之间,互相独立,互不干扰
持久性(Durability):当事务提交或回滚后,数据库会持久化的保存数据
编程式事务【了解】
就是将业务代码和事务代码放在一起书写,它的耦合性太高,开发中不使用
声明式事务
其实就是将事务代码(spring内置)和业务代码隔离开发,然后通过一段配置让他们组装运行,最后达到事务控制的目的(原理:AOP)
2、Spring事务管理器
PlatformTransactionManager
spring事务管理器的顶级接口,它为事务管理封装了一组独立于技术的方法,无论使用Spring的哪种事务管理策略(编程式或者声明式),事务管理器都是必须的<!--spring的orm--><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>5.1.5.RELEASE</version></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
<build><plugins><!-- 设置编译版本为1.8 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin></plugins></build>
<a name="BZ2Hh"></a>#### 配置文件:```java<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--开启注解扫描--><context:component-scan base-package="com.itfxp"/><!--引入jdbc.properties配置文件--><context:property-placeholder location="classpath:jdbc.properties"/><!--配置Druid数据库连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!--配置jdbcTemplate--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean></beans>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=UTF-8jdbc.username=rootjdbc.password=root~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-- 创建数据表CREATE TABLE account ( -- 账户表id INT PRIMARY KEY AUTO_INCREMENT,`name` VARCHAR(32),money DOUBLE);-- 添加数据INSERT INTO account (`name`, money) VALUES ('蝴蝶姐', 1000), ('罗志祥', 1000);
Dao层:
@Repositorypublic class AccountDaoImpl implements AccountDao {// 依赖jdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic void outUser(String outUser, Double money) {// 1.编写sqlString sql = "update account set money = money - ? where name = ?";// 2.执行sqljdbcTemplate.update(sql, money,outUser);}@Overridepublic void inUser(String inUser, Double money) {// 1.编写sqlString sql = "update account set money = money + ? where name = ?";// 2.执行sqljdbcTemplate.update(sql, money,inUser);}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~public interface AccountDao {/*** 转出操作* @param user 转出的账号* @param money 转出金额*/void outUser(String user,Double money);/*** 转入操作* @param user 转入的账号* @param money 转入金额*/void inUser(String user,Double money);}
serivice层:
@Servicepublic class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Overridepublic void transfer(String outUser, String inUser, Double money) {// 核心业务accountDao.outUser(outUser, money);accountDao.inUser(inUser, money);}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~public interface AccountService {/*** 转账* @param outUser 转出用户* @param inUser 转入用户* @param money 金额*/public void transfer(String outUser, String inUser, Double money);}
web层:
/*** 将单元测试的运行器,切换为Spring的运行器*/@RunWith(SpringRunner.class)/*** 加载配置文件*/@ContextConfiguration("classpath:applicationContext.xml")public class SpringTransferTest {@Autowiredprivate AccountService accountService;@Testpublic void test01() {accountService.transfer("罗志祥","蝴蝶姐",500.0);}}
三、Spring编程式事务
1、配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean>
2、事务的模板(作用于service层)
@Servicepublic class xxxServiceImpl implements xxxService{@Autowiredprivate PlatformTransactionManager transactionManager;public void method() {DefaultTransactionDefinition def = new DefaultTransactionDefinition();// 设置是否只读,为false才支持事务def.setReadOnly(false);// 设置隔离级别def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);// 设置事务的传播行为def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// 对事务管理器进行配置TransactionStatus status = transactionManager.getTransaction(def);try {// 业务操作// ......................// 提交事务transactionManager.commit(status);} catch (Exception e) {e.printStackTrace();// 回滚事务transactionManager.rollback(status);}}}
四、Spring声明式事务
1、xml方式
导入坐标
<!--spring的orm--><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>5.1.5.RELEASE</version></dependency><!--aspectj--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency>
引入事务的约束
xmlns:tx="http://www.springframework.org/schema/tx"http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd
事务管理器
<!--定义事务管理器信息 DefaultTransactionDefinition我们可以控制指定的方法,设置事务隔离级别、传播行为、是否只读、是否超时...name="transfer" 需要控制事务的方法名isolation="DEFAULT" 设置当前方法的事务隔离界别,mysql默认级别:repeatable_readpropagation="REQUIRED" 设置当前方法的事务传播行为 ,REQUIRED:当前方法必须有一个事务(单独 使用开启,别人调用加入对方事务)read-only="false" 当前方式为非只读(增删改用的)timeout="-1" 事务超时时间,-1:永不超时--><tx:advice id="txAdvice" transaction-manager="transactionManager"><!--定义事务管理器信息--><tx:attributes>//表示对所有的方法都进行事故管理<tx:method name="*"/>//具体划分<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/><tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/><tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/><tx:method name="find*" read-only="true" propagation="SUPPORTS"/><tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/></tx:attributes></tx:advice><!--配置aop--><aop:config><!--此标签仅支持Spring事务管理器使用通知+切点=切面--><aop:advisor advice-ref="txAdvice"pointcut="execution(* com.itfxp.service..*.*(..))"></aop:advisor></aop:config>
1、注解方式
开启事务注解
<!--开启事务注解支持--><tx:annotation-driven />
将@Transactional作用在方法上
用法同xml一样:@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = true,timeout = -1)
将@Transactional作用在方法上
当前类中的所有方法全部被事务管理
