前言:測試springboot版本 :springBootVersion = '2.0.5.RELEASE'
一 :搬運@Transactional
B. 如果加了事務,必須做好開發環境測試(測試環境也盡量觸發異常、測試回滾),確保事務生效。
C. 以下列了事務使用過程的注意事項,請大家留意。
1. 不要在接口上聲明@Transactional ,而要在具體類的方法上使用 @Transactional 注解,否則注解可能無效。
2.不要圖省事,將@Transactional放置在類級的聲明中,放在類聲明,會使得所有方法都有事務。故@Transactional應該放在方法級別,不需要使用事務的方法,就不要放置事務,比如查詢方法。否則對性能是有影響的。
3.使用了@Transactional的方法,對同一個類里面的方法調用, @Transactional無效。比如有一個類Test,它的一個方法A,A再調用Test本類的方法B(不管B是否public還是private),但A沒有聲明注解事務,而B有。則外部調用A之后,B的事務是不會起作用的。(經常在這里出錯)
4.使用了@Transactional的方法,只能是public,@Transactional注解的方法都是被外部其他類調用才有效,故只能是public。道理和上面的有關聯。故在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯,但事務無效。
5.經過在ICORE-CLAIM中測試,效果如下:
A.拋出受查異常XXXException,事務會回滾。
B.拋出運行時異常NullPointerException,事務會回滾。
C.Quartz中,execute直接調用加了@Transactional方法,可以回滾;間接調用,不會回滾。(即上文3點提到的)
D.異步任務中,execute直接調用加了@Transactional方法,可以回滾;間接調用,不會回滾。(即上文3點提到的)
E.在action中加上@Transactional,不會回滾。切記不要在action中加上事務。
F.在service中加上@Transactional,如果是action直接調該方法,會回滾,如果是間接調,不會回滾。(即上文3提到的)
G.在service中的private加上@Transactional,事務不會回滾。
二:搬運@Test
測試時使用save()方法向數據庫插入一條記錄,結果發現通過單元測試了,但是並沒有向數據庫插入一條記錄,一看日志,發現Spring-test對事務進行了回滾。
為了使測試數據不對數據庫造成污染,在使用Spring-test進行的單元測試的時候,默認會對事務進行回滾,即@Rollback
默認是true,如果想要測試數據不回滾,可設置@Rollback(value = false)
。如果是使用MySQL數據庫,在設置了自動回滾之后,如果發現事務依然沒有回滾,那么可以查看一下數據庫引擎是否是Innodb
,因為其他的數據庫引擎如MyISAM
、Memory
都不支持事務。
實際測試中,@Test @Transactional兩個注釋一起,對save方法不起作用呀。。。。。mysql數據庫引擎是Innodb。
hibernate的sql語句上有 這句:Rolled back transaction for test ,但是save不回滾。。。delete的方法有回滾效果。。。。
回滾對save無效舉例:
@Test @Transactional public void test1() { Author author = new Author(); author.setName("author1"); Article article = new Article(); article.setTitle("title"); article.setContent("內容"); article.setAuthor(author); Article article1 = new Article(); article1.setTitle("title1"); article1.setContent("內容1"); article1.setAuthor(author); List<Article> list = new LinkedList<>(); list.add(article); list.add(article1); author.setArticleList(list); authorDao.save(author); Author author1 = authorDao.findAll().get(0); List<Article> articleList = author1.getArticleList(); for (Article lists : articleList) { System.out.println(lists.toString()); } }
結果如下:可以從數據庫中查出數據。