天天看點

Spring事務隔離級别及事務傳播行為

作者:阿亮堅持

(1),事務隔離級别

事務隔離級别
  (1) 隻讀事務 readOnly 隻讀資料, 不更新資料
  (2) 必須其他事務寫完了,才能讀取
        isolation=Isolation.READ_COMMITTED , 資料庫預設事務隔離級别
  (3) 可重複讀 REPEATABLE_READ
    一,在讀的時候加行鎖
    二,第一次讀取後,此行資料就不能被其他事務寫, 
               為了對讀取值進行檢驗,再次讀取。
               兩次讀取結果相同
    三,不可避免幻讀
  (4) Serializable
    一,讀鎖寫鎖互斥, 可以避免 不可重複讀, 幻讀,
                                                       髒讀: 讀取未送出的資料, 解決方案加事務
                                   不可重複讀, 幻讀 差別
    1,不可重複讀重點在于 update 和 delete
    2,幻讀重點在于 insert
    二,極大的降低資料庫并發能力           

(2),事務傳播行為

事務傳播行為
  (1) Propagation.REQUIRED
    一,支援目前事務, 如果沒有事務就建立一個事務
    二,如果存在事務就會加入目前事務
  (2) Propagation.REQUIRES_NEW
    一,目前方法必須啟動新事務, 并在它自己的事務内運作
    二,如果有其他事務正在運作, 應該将它挂起
    三,外層事務不會影響内部事務的送出復原
    四,内部事務的異常則會影響外部事務           

(3),範例-部分代碼

<!--配置-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/grcdb05?useUnicode=true&characterEncoding=utf8" />
		<property name="username" value="root" />
		<property name="password" value="root" />
		<property name="defaultAutoCommit" value="false" />
	</bean>
	
	<!-- spring和MyBatis整合,不需要mybatis的配置映射檔案 -->
	<!-- 自動掃描mapping.xml檔案 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="/WEB-INF/mybatis/mybatis-config.xml"></property>
	</bean>
	<!-- SqlSessionTemplate 對象可以使用 SqlSessionFactory 作為構造方法的參數來建立 -->
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory" />
	</bean>
	
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>           
/**
 * @auther: xiongbl
 * @date: 2022/11/27 12:13
 * @desc: 測試學生類服務層
 */
@Service
public class StudentService {

    @Autowired
    private SqlSessionTemplate sqlSession;

    @Transactional(propagation = Propagation.REQUIRES_NEW
            , isolation = Isolation.REPEATABLE_READ
            , timeout = 1000
            , rollbackFor = RuntimeException.class)
    public void updateA() throws RuntimeException {

        String sqlState = "select count(1) age_count from t00_user where age > 18 ";
        Integer age_count = sqlSession.selectOne("com.entity.commonDao.queryInteger", sqlState);

        if(age_count > 0) {
            System.out.println("年齡大于18歲的學生,才能工作");
        }

    }

}