Spring Boot 揭祕與實戰(二) 數據存儲篇 - 聲明式事務管理

本文講解 Spring Boot 如何使用聲明式事務管理。javascript

博客地址:blog.720ui.com/java

聲明式事務

Spring 支持聲明式事務,使用 @Transactional 註解在方法上代表這個方法須要事務支持。此時,Spring 攔截器會在這個方法調用時,開啓一個新的事務,當方法運行結束且無異常的狀況下,提交這個事務。git

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

Spring Boot默認集成事務

Spring Boot 默認集成事務,因此無須手動開啓使用 @EnableTransactionManagement 註解,就能夠用 @Transactional註解進行事務管理。咱們若是使用到 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa,Spring Boot 會自動默認分別注入 DataSourceTransactionManager 或 JpaTransactionManager。spring

實戰演練

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

實體對象

咱們先建立一個實體對象。爲了便於測試,咱們對外提供一個構造方法。微信

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 相關

這裏,爲了測試事務,咱們只提供一個方法新增方法。spring-boot

@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 修飾的代表須要事務回滾。ui

@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

(完)

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

相關文章
相關標籤/搜索