Spring框架簡介⑩
事務的特性(ACID):
A: Atomic 原子性
表示組成一個事務的多個對資料庫的操作為一個不可分割的單元, 只有所有的操作都成功才算成功, 整個事務才會提交, 其中任何一個操作失敗了都會導致整個操作失敗, 事務則會回滾
C: Consistency 一致性
事務操作成功後, 資料庫所處的狀態和業務規則是一致(不變)的, 如果A賬戶給B賬戶匯100, 則A賬戶要減去100, B賬戶要加上100 兩個賬戶的總額是不變的
I: Isolation 隔離性
在多個對資料庫操作相同的資料併發時, 不同的事務有自己的資料空間, 事務與事務之間不受干擾(不是絕對的), 干擾程度受資料庫或者操作事務的隔離級別來決定, 隔離級別越高, 干擾就越低, 資料的一致性就越好, 而併發性則越差.
D: Durability 永續性
一旦事務提交成功, 資料就被持久化到資料庫, 不可以回滾, 重啟/關機都不會丟失資料了.
原子性由Spring的傳播特性來控制, 一致性和隔離性由資料庫的隔離級別來控制.
事務控制
配置檔案的配置(第一標頭檔案配置, 第二事務管理器的配置, 第三開啟事務註解驅動)
這是我的專案結構圖:
配置檔案:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- 配置屬性檔案的位置 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置資料來源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- 採用${xxx}的形式讀取屬性檔案中對應key的內容 -->
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pword}"></property>
<!-- 初始化連線數 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 最大連線數 -->
<property name="maxActive" value="${maxActive}"></property>
<!-- 最大空閒連線數 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 最小空閒連線數 -->
<property name="minIdle" value="${minIdle}"></property>
</bean>
<bean id="orderDao" class="com.rl.spring.dao.impl.OrderDaoImpl">
<property name="ds" ref="dataSource"></property>
</bean>
<bean id="detailDao" class="com.rl.spring.dao.impl.DetailDaoImpl">
<property name="ds" ref="dataSource"></property>
</bean>
<bean id="orderService" class="com.rl.spring.service.impl.OrderServiceImpl">
<property name="orderDao" ref="orderDao"></property>
</bean>
<bean id="detailService" class="com.rl.spring.service.impl.DetailServiceImpl">
<property name="orderDao" ref="orderDao"></property>
<property name="detailDao" ref="detailDao"></property>
</bean>
<!-- 定義事務管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事務管理的註解驅動 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
下面只貼上實現類的程式碼
OrderDaoImpl:
package com.rl.spring.dao.impl;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import com.rl.spring.dao.OrderDao;
import com.rl.spring.model.Order;
public class OrderDaoImpl implements OrderDao {
private DataSource ds;
private JdbcTemplate jt;
public void setDs(DataSource ds) {
this.ds = ds;
this.jt = new JdbcTemplate(ds);
}
@Override
public int saveOrder(Order order) {
String sql = "insert into t_order values(null, ?)";
jt.update(sql, new Object[] {order.getTotalPrice()});
return jt.queryForInt("SELECT LAST_INSERT_ID()");//該行程式碼的作用是讓資料庫返回主鍵
}
}
DetailDaoImpl
package com.rl.spring.dao.impl;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import com.rl.spring.dao.DetailDao;
import com.rl.spring.model.Detail;
import com.rl.spring.model.Order;
public class DetailDaoImpl implements DetailDao {
private DataSource ds;
private JdbcTemplate jt;
public void setDs(DataSource ds) {
this.ds = ds;
this.jt = new JdbcTemplate(ds);
}
@Override
public void saveDetail(Detail detail) {
String sql = "insert into t_detail values(null, ?, ?, ?)";
jt.update(sql, new Object[] {detail.getItemName(), detail.getQuantity(), detail.getOrderId()});
}
}
OrderServiceImpl(較簡單, 省略貼上上來)
DetailServiceImpl:
package com.rl.spring.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.rl.spring.dao.DetailDao;
import com.rl.spring.dao.OrderDao;
import com.rl.spring.model.Detail;
import com.rl.spring.model.Order;
import com.rl.spring.service.DetailService;
public class DetailServiceImpl implements DetailService {
DetailDao detailDao;
OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void setDetailDao(DetailDao detailDao) {
this.detailDao = detailDao;
}
@Transactional//事務管理註解
@Override
public void saveOrderAndDetail(Order order, Detail detail) {
Integer orderId = orderDao.saveOrder(order);
detail.setOrderId(orderId);
int i = 1/0;//設定執行期異常, 由於配置了Transactional註解, 所以事務會全部回滾
detailDao.saveDetail(detail);
}
}
測試程式碼:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.Detail;
import com.rl.spring.model.Order;
import com.rl.spring.service.DetailService;
import com.rl.spring.service.OrderService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
OrderService orderService;
@Autowired
DetailService detailService;
@Test
public void test() {
Order order = new Order();
order.setTotalPrice(100);
Detail detail = new Detail();
detail.setItemName("HUAWEI");
detail.setQuantity(1);
detailService.saveOrderAndDetail(order, detail);
}
}
@Transactional註解的本質是事務的傳播特性, 下面詳講事務的傳播特性
Spring的傳播特性
Required傳播特性(80%以上使用該傳播特性)
業務方法需要在一個事務中執行, 如果一個方法已經處在一個事務中那麼就加入到這個事務中, 否則就會建立一個新事務
如下圖:
傳播特性可配置:
Never傳播特性(極少使用):
指定的業務方法絕對不能在事務中執行, 如果在事務中執行了, 則會拋異常, 只有業務方法沒有事務才會正常執行.
MANDATORY傳播特性:
與Never相反, 只能在一個已經存在的事務中執行, 不能自己發起事務, 如果業務方法沒有事務的情況下, 則拋異常
SUPPORTS傳播特性:
如果業務方法已經在某個事務中被呼叫, 則業務方法就成為事務的一部分, 如果業務方法沒有在某個事務中被呼叫, SUPPORTS也支援該業務方法的執行(一句話, 開事務我就用事務, 不開事務我就不用事務, 但都可以執行)
NOT_SUPPORTED傳播特性:
永遠不支援事務(在有事務中該事務會被掛起)
REQUIRES_NEW傳播特性:
永遠使用自己建立的事務(如果已經存在事務則掛起它, 自己新建立), 假如自己new出來的這個事務回滾了, 是不會影響到另一個被掛起的事務的.
NESTED傳播特性:
主要區分於內外部事務, 如果內部事務做回滾, 是不會影響到外部事務的(因為NESTED會設定一個事務儲存點, 回滾到該儲存點後繼續執行外部事務); 而如果是外部事務做回滾, 該內外部事務全部回滾.
這點跟REQUIRES_NEW有區別, REQUIRES_NEW是不管是否內外部事務都互不影響.
====================================================
Spring系列暫時寫到這裡, 後續抽時間更一下事務的隔離級別, 接下來會更Hibernate系列.
相關文章
- Spring框架簡介⑨Spring框架
- Spring框架簡介⑧Spring框架
- Spring框架簡介⑦Spring框架
- Spring框架簡介⑥Spring框架
- Spring框架簡介⑤Spring框架
- Spring框架簡介④Spring框架
- Spring框架簡介③Spring框架
- Spring框架簡介②Spring框架
- Spring框架簡介①Spring框架
- Spring 簡介Spring
- Scrapy框架簡介框架
- SpringMVC框架簡介②SpringMVC框架
- SpringMVC框架簡介①SpringMVC框架
- Hibernate框架簡介⑤框架
- Hibernate框架簡介④框架
- Hibernate框架簡介③框架
- Hibernate框架簡介②框架
- Hibernate框架簡介①框架
- HTML 框架簡介HTML框架
- spring框架的介紹Spring框架
- Spring Batch 簡介SpringBAT
- Spring框架之IOC介紹Spring框架
- [轉]SSH框架簡介框架
- Spring常用Annotation簡介Spring
- Spring_Framework_簡介SpringFramework
- Spring系列.Bean簡介SpringBean
- Spring(2)-AOP簡介Spring
- Flutter路由框架Fluro簡介Flutter路由框架
- uni-app 框架簡介APP框架
- wsgiref模組、web框架、django框架簡介Web框架Django
- Spring Security中AuthorizationManager簡介Spring
- Spring AOP基礎簡介Spring
- Spring Cloud Gateway使用簡介SpringCloudGateway
- Spring中雲事件簡介Spring事件
- Spring 框架基礎(06):Mvc架構模式簡介,執行流程詳解Spring框架MVC架構模式
- Spring框架系列(2) - Spring簡單例子引入Spring要點Spring框架單例
- 工作流框架Flowable 簡介框架
- OSX 攻擊框架Empyre簡介框架