什么是事務(wù)?
它是一個操作序列逼纸,這些操作要么都執(zhí)行,要么都不執(zhí)行济蝉,它是一個不可分割的工作單位杰刽。它保證了用戶的每一次操作都是可靠的,即便出現(xiàn)了異常的訪問情況王滤,也不至于破壞后臺數(shù)據(jù)的完整性
事務(wù)的特性
一個事務(wù)是有下列屬性的一個工作單元:
原子性(ATOMICITY):
一個事務(wù)要被完全的無二義性的做完或撤消贺嫂。在任何操作出現(xiàn)一個錯誤的情況下,構(gòu)成事務(wù)的所有操作的效果必須被撤消雁乡,數(shù)據(jù)應(yīng)被回滾到以前的狀態(tài)第喳。
一致性(CONSISTENCY):
一個事務(wù)應(yīng)該保護(hù)所有定義在數(shù)據(jù)上的不變的屬性(例如完整性約束)。在完成了一個成功的事務(wù)時踱稍,數(shù)據(jù)應(yīng)處于一致的狀態(tài)曲饱。換句話說,一個事務(wù)應(yīng)該把系統(tǒng)從一個一致-狀態(tài)轉(zhuǎn)換到另一個一致狀態(tài)珠月。舉個例子扩淀,在關(guān)系數(shù)據(jù)庫的情況下,一個一致的事務(wù)將保護(hù)定義在數(shù)據(jù)上的所有完整性約束啤挎。
隔離性(ISOLATION):
在同一個環(huán)境中可能有多個事務(wù)并發(fā)執(zhí)行驻谆,而每個事務(wù)都應(yīng)表現(xiàn)為獨立執(zhí)行。串行的執(zhí)行一系列事務(wù)的效果應(yīng)該同于并發(fā)的執(zhí)行它們庆聘。這要求兩件事:
在一個事務(wù)執(zhí)行過程中胜臊,數(shù)據(jù)的中間的(可能不一致)狀態(tài)不應(yīng)該被暴露給所有的其他事務(wù)。
兩個并發(fā)的事務(wù)應(yīng)該不能操作同一項數(shù)據(jù)伙判。數(shù)據(jù)庫管理系統(tǒng)通常使用鎖來實現(xiàn)這個特征区端。
持久性(DURABILITY):
一個被完成的事務(wù)的效果應(yīng)該是持久的。
Spring的事務(wù)管理
分類
- 編程式事務(wù)管理
- 聲明式事務(wù)管理(常用)
- 基于xml配置文件實現(xiàn)
- 基于注解實現(xiàn)
api
Spring針對不同的dao層都提供了不同的實現(xiàn)類
轉(zhuǎn)賬環(huán)境
配置事務(wù)管理器
- 創(chuàng)建service和dao類澳腹,完成注入關(guān)系
- service業(yè)務(wù)邏輯層
- dao層,單獨對數(shù)據(jù)庫操作杨何,在dao層不添加業(yè)務(wù)
<!-- 配置c3p0連接池 --> <!-- 創(chuàng)建對象 --> <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/testspring"></property> <property name="user" value="root"></property> <property name="password" value=""></property> </bean> <bean id="ordersService" class="com.ljy.service.OrdersService"> <property name="ordersDao" ref="ordersDao"></property> </bean> <bean id="ordersDao" class="com.ljy.dao.OrdersDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> <!-- 源代碼中有dataSource --> </bean>
- 需求:lucy給lily轉(zhuǎn)賬1000
未加事務(wù)
dao:
public class OrdersDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//少錢的方法
public void lessMoney(){
String sql = "update account set salary=salary-? where username=?";
jdbcTemplate.update(sql,1000,"lucy");
}
//多錢的方法
public void moreMoney(){
String sql = "update account set salary=salary+? where username=?";
jdbcTemplate.update(sql,1000,"lily");
}
}
service:
public class OrdersDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//少錢的方法
public void lessMoney(){
String sql = "update account set salary=salary-? where username=?";
jdbcTemplate.update(sql,1000,"lucy");
}
//多錢的方法
public void moreMoney(){
String sql = "update account set salary=salary+? where username=?";
jdbcTemplate.update(sql,1000,"lily");
}
}
如果lucy少了1000后出現(xiàn)了異常 程序不會繼續(xù)執(zhí)行 lily也不會多1000 酱塔。
解決方法
添加事務(wù)解決,出現(xiàn)異常時回滾操作
-
聲明式事務(wù)管理(xml配置)
配置事務(wù)管理器
配置事物的增強<!-- 配置事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 注入datasource 表明對哪個數(shù)據(jù)庫進(jìn)行操作 --> <property name="dataSource" ref="dataSource"></property> </bean>
配置切面<!-- 配置事物的增強 --> <tx:advice id="txadvice" transaction-manager="transactionManager"> <!-- 做事務(wù)操作 --> <tx:attributes> <!-- 設(shè)置進(jìn)行實務(wù)操作的方法匹配規(guī)則 --> <tx:method name="account*" propagation="REQUIRED"/> <!-- 以account開頭的所有方法都可以執(zhí)行這個事務(wù) --> </tx:attributes> </tx:advice>
<!-- 配置切面產(chǎn)生代理 --> <aop:config> <!-- 切入點 --> <aop:pointcut expression="execution(* com.ljy.Service.*(..)" id="pointcut1"/> <!-- 切面 --> <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"></aop:aspect> </aop:config>
-
聲明式事務(wù)管理(注解)
配置事務(wù)管理器
配置事務(wù)注解
在要是用事務(wù)的方法所有類上面添加注解<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional public class OrdersService{
事務(wù)做了回滾后 數(shù)據(jù)庫的數(shù)據(jù)不會有更改