Spring Boot 揭祕與實戰(二) 資料儲存篇 - 宣告式事務管理

樑桂釗發表於2017-01-05

本文講解 Spring Boot 如何使用宣告式事務管理。

部落格地址:blog.720ui.com/

宣告式事務

Spring 支援宣告式事務,使用 @Transactional 註解在方法上表明這個方法需要事務支援。此時,Spring 攔截器會在這個方法呼叫時,開啟一個新的事務,當方法執行結束且無異常的情況下,提交這個事務。

Spring 提供一個 @EnableTransactionManagement 註解在配置類上來開啟宣告式事務的支援。使用了 @EnableTransactionManagement 後,Spring 會自動掃描註解 @Transactional 的方法和類。

Spring Boot預設整合事務

Spring Boot 預設整合事務,所以無須手動開啟使用 @EnableTransactionManagement 註解,就可以用 @Transactional註解進行事務管理。我們如果使用到 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa,Spring Boot 會自動預設分別注入 DataSourceTransactionManager 或 JpaTransactionManager。

實戰演練

我們在前文「Spring Boot 揭祕與實戰(二) 資料儲存篇 - MySQL」的案例上,進行實戰演練。

實體物件

我們先建立一個實體物件。為了便於測試,我們對外提供一個構造方法。

public class Author {
    private Long id;
    private String realName;
    private String nickName;

    public Author() {}
    public Author(String realName, String nickName) {
        this.realName = realName;
        this.nickName = nickName;
    }
    // SET和GET方法
}複製程式碼

DAO 相關

這裡,為了測試事務,我們只提供一個方法新增方法。

@Repository("transactional.authorDao")
public class AuthorDao  {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public int add(Author author) {
        return jdbcTemplate.update("insert into t_author(real_name, nick_name) values(?, ?)", 
                author.getRealName(), author.getNickName());
    }

}複製程式碼

Service 相關

我們提供三個方法。通過定義 Author 的 realName 欄位長度必須小於等於 5,如果欄位長度超過規定長度就會觸發引數異常。

值得注意的是,noRollbackFor 修飾表明不做事務回滾,rollbackFor 修飾的表明需要事務回滾。

@Service("transactional.authorService")
public class AuthorService {

    @Autowired
    private AuthorDao authorDao;

    public int add1(Author author) {
        int n = this.authorDao.add(author);    
        if(author.getRealName().length() > 5){
            throw new IllegalArgumentException("author real name is too long.");
        }
        return n;
    }

    @Transactional(noRollbackFor={IllegalArgumentException.class})
    public int add2(Author author) {
        int n = this.authorDao.add(author);    
        if(author.getRealName().length() > 5){
            throw new IllegalArgumentException("author real name is too long.");
        }
        return n;
    }

    @Transactional(rollbackFor={IllegalArgumentException.class})
    public int add3(Author author) {
        int n = this.authorDao.add(author);    
        if(author.getRealName().length() > 5){
            throw new IllegalArgumentException("author real name is too long.");
        }
        return n;
    }
}複製程式碼

測試,測試

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(WebMain.class)
public class TransactionalTest {

    @Autowired
    protected AuthorService authorService;

    //@Test
    public void add1() throws Exception {
        authorService.add1(new Author("樑桂釗", "樑桂釗"));
        authorService.add1(new Author("LiangGzone", "LiangGzone"));
    }

    //@Test
    public void add2() throws Exception {
        authorService.add2(new Author("樑桂釗", "樑桂釗"));
        authorService.add2(new Author("LiangGzone", "LiangGzone"));
    }

    @Test
    public void add3() throws Exception {
        authorService.add3(new Author("樑桂釗", "樑桂釗"));
        authorService.add3(new Author("LiangGzone", "LiangGzone"));
    }
}複製程式碼

我們分別對上面的三個方法進行測試,只有最後一個方法進行了事務回滾。

原始碼

相關示例完整程式碼: springboot-action

(完)

更多精彩文章,盡在「服務端思維」微信公眾號!

Spring Boot 揭祕與實戰(二) 資料儲存篇 - 宣告式事務管理

相關文章