1.什麼是事務
二.事務的傳播性,簡單的引用
創建maven項目,在pom.xml中加載架包
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn</groupId>
<artifactId>spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- 加載spring的包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
<!-- 添加jdbc的架包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!-- 加載數據庫的架包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<!-- 面向切面編程 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
創建連接數據的四要素jdbc.properties文件
url=jdbc:mysql://localhost:3306/news
driverClassName=com.mysql.jdbc.Driver
userName1=root
password=123456
創建spring.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
">
<!-- 掃描bean -->
<context:component-scan base-package="less04.testm"></context:component-scan>
<context:property-placeholder location="classpath:/less04/jdbc.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${url}" ></property>
<property name="username" value="${userName1}" ></property>
<property name="password" value="${password}" ></property>
<property name="driverClassName" value="${driverClassName}" ></property>
</bean>
<!-- 事務管理器 不再使用jdbc的commit和rollback 必須由事務管理器提供 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 定義通知 通知的代碼 spring已經實現 -->
<tx:advice id="myAdvise" transaction-manager="transactionManager">
<tx:attributes>
<!--
propagation="REQUIRED" 方法和方法之間父子關係
REQUIRED 沒有事務創建一個事務 有事務使用當前事務
REQUIRED_NEW 不管父方法是否存在事務 都會新建事務
SUPPORTS 父方法存在事務 使用當前事務 沒有事務 使用jdbc的事務(自動提交)
NOT_SUPPORTED 不管父方法是否存在事務 都不會使用事務(掛起事務)
MANDATORY 必須在事務環境下運行 父方法沒有事務 拋出異常
No existing transaction found for transaction marked with propagation 'mandatory'
NEVER 父方法不能存在 事務 有事務拋出異常
Existing transaction found for transaction marked with propagation 'never'
isolation="DEFAULT"隔離級別
DEFAULT使用數據庫本身的隔離級別ORACLE(讀已提交)MYSQL(可重複讀)
READ_UNCOMMITTED spring實現讀未提交(髒讀)
REA_COMMITTED spring實現讀已提交(不重複讀+幻讀)
REPEATABLE_READ spring實現可重複讀(幻讀)
SERIALIZABLE spring實現串行化(已解決)
spring事務運行過程中碰到運行時異常自動回滾 非運行時異常不會回滾
rollback-for=""指定會自動回滾的非運行時異常
no-rollback-for=""指定某些運行時異常拋出時不回滾
只讀事務(除特定的方法以外其他的業務邏輯方法都不應該操作事務)
read-only="true"設置只讀事務
timeout=""設置超時時間
-->
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="save*" />
<tx:method name="delete*"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 定義切點 advice-ref引用通知 -->
<aop:config>
<aop:pointcut expression="execution(* less04.testm.dao.*.*(..)) " id="myPoint"/>
<aop:advisor advice-ref="myAdvise" pointcut-ref="myPoint"/>
</aop:config>
</beans>
持久層
package less04.testm.dao;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class AcDaoImpl {
@Autowired
JdbcTemplate jdbc;
@Autowired
BcDaoImpl b;
public void updateAminus(int money) throws SQLException{
//扣錢
String sql="update mymoney set lostedmoney=lostedmoney-"+money+" where usid=1";
jdbc.execute(sql);
//加錢
b.saveBadd(money);
int i=5/0;
}
}
package less04.testm.dao;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BcDaoImpl {
@Autowired
JdbcTemplate jdbc;
public void saveBadd(int money) throws SQLException{
String sql="update mymoney set lostedmoney=lostedmoney+"+money+" where usid=2";
jdbc.execute(sql);
}
}
測試main方法
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import less04.testm.dao.AcDaoImpl;
/**
* 編程式事務
* 聲明式事務
* xml聲明(全局)
* 註解聲明
*/
public class TestTa {
static AcDaoImpl myMoneyDao;
static{
ApplicationContext context = new GenericXmlApplicationContext("classpath:less04/testm/spring.xml");
myMoneyDao=(AcDaoImpl)context.getBean("acDaoImpl");
}
public static void main(String[] args) throws SQLException {
myMoneyDao.updateAminus(10);
}
}
三.事務的隔離級別
1.什麼是事務的隔離級別
事務隔離級別指的是一個事務對數據的修改與另一個並行的事務的隔離程度,當多個事務同時訪問相同數據時,如果沒有采取必要的隔離機制,就可能發生以下問題:
髒讀:一個事務讀到另一個事務未提交的更新數據。
幻讀:例如第一個事務對一個表中的數據進行了修改,比如這種修改涉及到表中的“全部數據行”。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入“一行新數據”。那麼,以後就會發生操作第一個事務的用戶發現表中還存在沒有修改的數據行,就好象發生了幻覺一樣。
不可重複讀:比方說在同一個事務中先後執行兩條一模一樣的select語句,期間在此次事務中沒有執行過任何DDL語句,但先後得到的結果不一致,這就是不可重複讀。
2.Spring支持的隔離級別1.DEFAULT 使用數據庫本身的隔離級別ORACLE(讀已提交)MYSQL(可重複讀)
2. READ_UNCOMMITTED 讀未提交(髒讀)最低的隔離級別,一切皆有可能。 spring實現讀未提交(髒讀)
3.REA_COMMITTED
讀已提交,ORACLE默認隔離級別,有幻讀以及不可重複讀風險 .spring 實現讀已提交(不重複讀+幻讀)
4.REPEATABLE_READ
可重複讀,解決不可重複讀的隔離級別,但還是有幻讀風險.spring實現可重複讀(幻讀)
5.SERIALIZABLE
串行化,最高隔離級別,杜絕一切隱患,缺點是效率低.spring實現串行化(已解決)
3.事務的回滾
spring事務運行過程中碰到運行時異常自動回滾 非運行時異常不會回滾
rollback-for=""指定會自動回滾的非運行時異常
no-rollback-for=""指定某些運行時異常拋出時不回滾
timeout=""設置超時時間 超時時間一般在5到20之間