E3 2021:《They Always Run》演示 爽快橫版動作
阿新 • • 發佈:2021-06-14
事務基礎
事務的概念
- 事務指資料庫中多個操作合併在一起形成的操作序列
- 由多個操作組成的一個邏輯單元,組成這個邏輯單元的多個操作要麼都成功要麼都失敗
事務的特性
-
原子性(Atomicity)
- 指事務是一個不可分割的整體,其中的操作要麼全執行或全不執行
-
一致性(Consistency)
- 事務前後資料的完整性必須保持一致
-
隔離性(Isolation)
- 事務的隔離性是多個使用者併發訪問資料庫時,
- 資料庫為每一個使用者開啟的事務,不能被其他事務的操作資料所幹擾,
- 多個併發事務之間要相互隔離
-
永續性(Durability)
- 永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,
- 接下來即使資料庫發生故障也不應該對其有任何影響
名詞解釋
- 髒讀
- 允許讀取未提交的資訊
- 解決方案:表級讀鎖
- 不可重複讀
- 讀取過程中單個數據發生了變化
- 解決方案:行級寫鎖
- 幻讀
- 讀取過程中資料條目發生了變化
- 解決方案:表級寫鎖
隔離級別
- Read uncommitted
- 存在:髒讀、不可重複讀、幻讀
- Read committed
- 存在:不可重複讀、幻讀
- 解決:髒讀
- Repeatable read
- 存在:幻讀
- 解決:髒讀、不可重複讀
- Serializable
- 解決:髒讀、不可重複讀、幻讀
程式設計式事務控制
applicationContext.xml 配置
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <context:property-placeholder location="classpath:*.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="accountService" class="com.asaawan.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="typeAliasesPackage" value="com.asaawan.domain"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.asaawan.dao"/> </bean> <!-- aop 控制事務 --> <!-- 為 TxAdvice 注入資料來源 --> <bean id="txAdvice" class="com.asaawan.aop.TxAdvice"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 為 transfer 方法新增事務控制 --> <aop:config> <aop:pointcut id="pt" expression="execution(* *..transfer(..))"/> <aop:aspect ref="txAdvice"> <aop:around method="transactionManager" pointcut-ref="pt"/> </aop:aspect> </aop:config> </beans>
TxAdvice 配置
public class TxAdvice {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public Object transactionManager(ProceedingJoinPoint pjp) throws Throwable {
// 開啟事務
// 建立事務管理器併為事務管理器設定與資料層相同的資料來源
PlatformTransactionManager ptm = new DataSourceTransactionManager(dataSource);
// 建立事務定義物件
TransactionDefinition td = new DefaultTransactionDefinition();
// 建立事務狀態物件,用於控制事務執行
TransactionStatus ts = ptm.getTransaction(td);
// 執行切入點方法
Object ret = pjp.proceed(pjp.getArgs());
// 提交事務
ptm.commit(ts);
// 返回資料
return ret;
}
}
宣告式事務控制
applicationContext.xml 配置
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:*.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.asaawan.domain"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.asaawan.dao"/>
</bean>
<bean id="accountService" class="com.asaawan.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!-- tx 控制事務 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--定義事務管理的通知類-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!--定義控制的事務-->
<tx:attributes>
<tx:method
name="transfer"
read-only="false"
timeout="-1"
isolation="DEFAULT"
no-rollback-for=""
rollback-for=""
propagation="REQUIRED"
/>
<!--<tx:method name="transfer" read-only="false"/>-->
<!--name="transfer" 待新增事務的方法名錶達式(支援*號萬用字元),例如get*
read-only="false" 設定事務的讀寫屬性,true為只讀,false為只寫
timeout="-1" 設定事務超時時長,單位秒
isolation="DEFAULT" 設定事務的隔離級別,該隔離級設定是基於Spring的設定,非資料庫端
no-rollback-for="" 設定事務中不回滾的異常,多個異常間使用 ',' 分割
rollback-for="" 設定事務中必回滾的異常,多個異常間使用 ',' 分割
propagation="REQUIRED" 設定事務的傳播行為-->
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.asaawan.service.*Service.*(..))"/>
<aop:pointcut id="pt2" expression="execution(* com.asaawan.dao.*.b(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt2"/>
</aop:config>
</beans>
applicationContext.xml 註解
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:*.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.asaawan.domain"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.asaawan.dao"/>
</bean>
<bean id="accountService" class="com.asaawan.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!-- tx 事務控制註解版 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 開啟事務註解驅動 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
AccountService 配置
//對當前介面的所有方法新增事務
//新增事務一般在 *Service 新增
@Transactional(isolation = Isolation.DEFAULT)
public interface AccountService {
/**
* 轉賬操作
* @param outName 出賬使用者名稱
* @param inName 入賬使用者名稱
* @param money 轉賬金額
*/
//對當前方法新增事務,該配置將替換介面的配置
@Transactional(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
rollbackFor = {}, //java.lang.ArithmeticException.class, IOException.class
noRollbackFor = {},
propagation = Propagation.REQUIRED
)
public void transfer(String outName, String inName, Double money);
}
宣告式事務控制純註解
TxManagerConfig 註解
public class TxManagerConfig {
@Bean
public PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
SpringConfiguration 註解
@Configuration
@ComponentScan("com.asaawan")
@PropertySource(value = {"classpath:jdbc.properties"},ignoreResourceNotFound = true)
@Import({JdbcConfiguration.class, MyBatisConfiguration.class})
@EnableTransactionManagement
public class SpringConfiguration {
}
aop:advice 與 aop:advisor
aop:advice
- 配置的通知類可以是普通 java 物件,不實現介面,也不使用繼承關係
aop:advisor
- 配置的通知類必須實現通知介面
MethodBeforeAdvice
AfterReturningAdvice
ThrowsAdvice
- ...
事務的傳播行為
概念
- 指的就是當一個事務方法被另一個事務方法呼叫時,這個事務方法應該如何進行