Spring——事務操作
1、事務概念
a)什麼是事務
(1)事務是數據庫操作最基本單元,邏輯上一組操作,要麼都成功,如果有一個失敗所有操 作都失敗
(2)典型場景:銀行轉賬 張三 轉賬 100 元 給 李四; 張三少 100,李四多 100
b)事務四個特性(ACID) (1)原子性 (2)一致性 (3)隔離性 (4)持久性 可查看這篇文章描述
2、事務操作(模擬事務操作環境)
a)創建 service,搭建 dao,完成對象創建和注入關係
//(1)service 注入 dao,在 dao 注入 JdbcTemplate,在 JdbcTemplate 注入 DataSource
@Service
public class UserService {
//注入 dao
@Autowired
private UserDao userDao;
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
}
b)在 dao 創建兩個方法:多錢和少錢的方法, 在 service 創建方法(轉賬的方法)
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
//lucy 轉賬 100 給 mary
//少錢
@Override
public void reduceMoney() {
String sql = "update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
//多錢
@Override
public void addMoney() {
String sql = "update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"mary");
}
}
@Service
public class UserService {
//注入 dao
@Autowired
private UserDao userDao;
//轉賬的方法
public void accountMoney() {
//lucy 少 100
userDao.reduceMoney();
//mary 多 100
userDao.addMoney();
}
}
/**
上邊代碼正常執行沒有問題,
但是如果代碼執行過程中出現異常,有問題,如下模擬異常!
*/
@Service
public class UserService {
//這裏執行後將會產生錯誤(異常),lucy 少 100後,mary不會多 100,這就不對了!!
private UserDao userDao;
//轉賬方法
public void accountMoney(){
userDao.reduceMoney();//lucy 少 100
int x=10/0;
userDao.addMoney(); //mary 多 100
}
}
//解決上邊的異常方法——【編程式事務(傳統方法)】
//轉賬的方法
public void accountMoney() {
try {
//第一步 開啓事務
//第二步 進行業務操作
//lucy少100
userDao.reduceMoney();
//模擬異常
int i = 10/0;
//mary多100
userDao.addMoney();
//第三步 沒有發生異常,提交事務
}catch(Exception e) {
//第四步 出現異常,事務回滾
}
}
3、事務操作(Spring 事務管理介紹)
1、事務添加到 JavaEE 三層結構裏面 Service 層(業務邏輯層)
2、在 Spring 進行事務管理操作 ;兩種方式:編程式事務管理、聲明式事務管理(推薦使用)
3、聲明式事務管理 (1)基於註解方式(推薦使用) (2)基於 xml 配置文件方式
4、在 Spring 進行聲明式事務管理,底層使用 AOP 原理
5、Spring 事務管理 API :提供一個接口,代表事務管理器,這個接口針對不同的框架提供不同的實現類
4、註解聲明式事務管理
<!--1、在 spring 配置文件配置事務管理器-->
<!--創建事務管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入數據源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2、在 spring 配置文件,開啓事務註解,引入名稱空間!-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.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">
<!--開啓事務註解-->
<tx:annotation-driven transactionmanager="transactionManager"></tx:annotation-driven>
<!--3、在 service 類上面(或者 service 類裏面方法上面)添加事務註解-->
<!--
(1)@Transactional,這個註解添加到類上面,也可以添加方法上面
(2)如果把這個註解添加類上面,這個類裏面所有的方法都添加事務
(3)如果把這個註解添加方法上面,爲這個方法添加事務——@Transactional
-->
5、事務操作(聲明式事務管理參數配置)
Transactional(事務傳播行爲)
a)在 service 類上面添加註解@Transactional,在這個註解裏面可以配置事務相關參數
b)propagation(事務傳播行爲):多事務方法直接進行調用,這個過程中事務 是如何進行管理的
c)spring框架事務傳播行爲有七種:下面只介紹常用的兩種傳播行爲
@Transactional(propagation = Propagation.REQUIRED,) //事務一 public void add(){ //調用update方法 update(); } public void update(){ //事務二 }
(1)REQUIRED:如果add方法本身沒有事務,調用update方法後,update使用當前add方法裏面的事務;
如果add方法本身沒有事務,調用update方法後,創建新的事務
(2)REQUIRED_NEW:使用add調用update方法,不論add方法是否有事務,都會創建新的事務。
ioslation(事務隔離級別)
a)事務有特性成爲隔離性,多事務操作之間不會產生影響。不考慮隔離性產生很多問題
b)有三個讀問題:髒讀、不可重複讀、虛(幻)讀 可查看這裏介紹
髒讀: 一個未提交事務讀取到另一個未提交事務的數據
不可重複讀: 一個未提交事務讀取到另一提交事務修改數據
虛讀: 一個未提交事務讀取到另一提交事務添加數據
c))解決:通過設置事務隔離級別,解決讀問題
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
timeout:超時時間
(1)事務需要在一定時間內進行提交,如果不提交進行回滾 (2)默認值是 -1(不超時) ,設置時間以秒單位進行計算
readOnly:是否只讀
(1)讀:查詢操作,寫:添加修改刪除操作
(2)readOnly 默認值 false,表示可以查詢,可以添加修改刪除操作
(3)設置 readOnly 值是 true,設置成 true 之後,只能查詢
rollbackFor:回滾
設置出現哪些異常進行事務回滾
noRollbackFor:不回滾
設置出現哪些異常不進行事務回滾
6、事務操作(XML 聲明式事務管理)
a)、在 spring 配置文件中進行配置 :第一步 配置事務管理器 第二步 配置通知 第三步 配置切入點和切面
<!--1 創建事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入數據源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txadvice">
<!--配置事務參數-->
<tx:attributes>
<!--指定哪種規則的方法上面添加事務-->
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--<tx:method name="account*"/>-->
</tx:attributes>
</tx:advice>
<!--3 配置切入點和切面-->
<aop:config>
<!--配置切入點-->
<aop:pointcut id="pt" expression="execution(*
com.atguigu.spring5.service.UserService.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
7、事務操作(完全註解聲明式事務管理)
//1、創建配置類,使用配置類替代 xml 配置文件
@Configuration //配置類
@ComponentScan(basePackages = "com.atguigu") //組件掃描
@EnableTransactionManagement //開啓事務
public class TxConfig {
//創建數據庫連接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///test");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
//創建 JdbcTemplate 對象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {//從IOC容器中拿到配置注入的數據源
//到 ioc 容器中根據類型找到 dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入 dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//創建事務管理器
@Bean
public DataSourceTransactionManager
getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}