一、事务概述
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.xsd
http://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.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=UTF-8
jdbc.username=root
jdbc.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层:
@Repository
public class AccountDaoImpl implements AccountDao {
// 依赖jdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void outUser(String outUser, Double money) {
// 1.编写sql
String sql = "update account set money = money - ? where name = ?";
// 2.执行sql
jdbcTemplate.update(sql, money,outUser);
}
@Override
public void inUser(String inUser, Double money) {
// 1.编写sql
String sql = "update account set money = money + ? where name = ?";
// 2.执行sql
jdbcTemplate.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层:
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
public 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 {
@Autowired
private AccountService accountService;
@Test
public 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层)
@Service
public class xxxServiceImpl implements xxxService{
@Autowired
private 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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
事务管理器
<!--
定义事务管理器信息 DefaultTransactionDefinition
我们可以控制指定的方法,设置事务隔离级别、传播行为、是否只读、是否超时...
name="transfer" 需要控制事务的方法名
isolation="DEFAULT" 设置当前方法的事务隔离界别,mysql默认级别:repeatable_read
propagation="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作用在方法上
当前类中的所有方法全部被事务管理