1. 程式人生 > >SpringBoot實戰筆記:24_Spring Boot 的事務支援

SpringBoot實戰筆記:24_Spring Boot 的事務支援

24_Spring Boot 的事務支援

  • 所有的資料訪問技術都有事務處理機制,這些技術提供了API用來開啟事務,提交事務來完成資料操作,或者在發生錯誤的時候回滾資料。
  • Spring 的事務機制是用統一的機制來處理不同的資料訪問技術的事務處理。
  • Spring 的事務機制提供了一個 PlatformTransactionManager 介面,不同的資料訪問技術的事務使用不同的介面實現。
資料訪問技術 實現類
JDBC DataSourceTransactionManager
JPA JpaTransactionManager
Hibernate HibernateTransactionManager
JDO JdoTransactionManager
分散式事務 JtaTransactionManager

定義事務管理器的程式碼如下

@Bean
public PlatformTransactionManager transactionManager(){
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setDataSource(dataSource());
    return
transactionManager; }

1,宣告式事務

Spring 支援宣告式事務,即使用註解來選擇需要使用事務的方法(切入點),它使用 @Transactional 註解在方法上,宣告該方法需要事務支援,這是一個基於 AOP 的實現操作。

@Transactional 註解是 org.springframework.transaction.annotation 包下的

Spring 提供了一個 @EnableTransactionManager 註解,在配置類上來開啟宣告式事務的支援。會自動掃註解 @Transactional 的方法和類(表示該類中所有public的方法都需要開啟事務的)。

2,Spring Data JPA 的事務支援

Spring Data JPA 對所有的預設方法都開啟了事務支援,且查詢類事務預設啟用 readOnly=true 屬性。
可以檢視 SimpleJpaRepository 類的原始碼


3,Spring Boot 的事務支援:自動配置的事務管理器

  • 在使用JDBC作為資料訪問技術的時候,Spring Boot 為我們定義了 PlatformTransactionManager 的實現 DataSourceTransactionManager 的Bean;
  • 在使用JPA作為資料訪問技術的時候,Spring Boot 為我們定義了 PlatformTransactionManager 的實現 JpaTransactionManager 的Bean;

4,Spring Boot 的事務支援:自動開啟註解事務的支援

  • Spring Boot 專門用於配置事務的類為 :TransactionAutoConfiguration,此配置類依賴於 JpaBaseConfigurationDataSourceTransactionManagerAutoConfiguration
  • DataSourceTransactionManagerAutoConfiguration 裡開啟了對宣告式事務的支援
  • 所以在 Spring Boot中,無需顯示的開啟使用 @EnableTransactionManager 註解

5,新建Spring Boot 專案:演示使用異常導致事務回滾

  • 匯入 webjpa 依賴
  • 新增 ojdbc6.jar 依賴,在 application.properties 檔案中新增配置

6,建立實體類Person

  • 屬性:id(主鍵、自增),name,address,age
  • 空引數構造方法,set/get方法
  • 別忘了在類上註解 :@Entity

7,建立實體類的Repository介面(DAO)

public interface PersonRepository extends JpaRepository<Person,Long>{

}

8,建立對應的Service 層

package com.zyf.service;

import com.zyf.domain.Person;

/**
 * Created by zyf on 2018/3/13.
 */
public interface PersonService {
    /**
     * 演示回滾
     */
    Person savePersonWithRollBack(Person person);

    /**
     * 演示不會滾
     */
    Person savePersonWithoutRollBack(Person person);
}
package com.zyf.service.impl;

import com.zyf.dao.PersonRepository;
import com.zyf.domain.Person;
import com.zyf.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by zyf on 2018/3/13.
 */
@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    PersonRepository personRepository;

    //通過rollbackfor屬性指定:出現該異常則資料回滾
    @Transactional(rollbackFor = {IllegalArgumentException.class})
    @Override
    public Person savePersonWithRollBack(Person person) {
        Person p = personRepository.save(person);
        if(person.getName().equals("zyf")){
            throw new IllegalArgumentException("不好意思不能存,回滾啦");
        }
        return p;
    }

    //通過noRollbackFor屬性指定:出現該異常則資料不回滾
    @Transactional(noRollbackFor = {IllegalArgumentException.class})
    @Override
    public Person savePersonWithoutRollBack(Person person) {
        Person p = personRepository.save(person);
        if(person.getName().equals("zyf")){
            throw new IllegalArgumentException("不好意思不能存,回滾啦");
        }
        return p;
    }
}

9,控制器

package com.zyf.controller;

import com.zyf.domain.Person;
import com.zyf.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by zyf on 2018/3/13.
 */
@Controller
public class PersonController {

    @Autowired
    PersonService personService;

    @RequestMapping("/rollback")
    public Person rollback(Person person){
        return personService.savePersonWithRollBack(person);
    }

    @RequestMapping("/norollback")
    public Person noRollback(Person person){
        return personService.savePersonWithoutRollBack(person);
    }
}

10,測試

訪問不回滾

依然存進去了

訪問回滾的話資料庫中是不會插入新資料的