在JPA開發中遇到一個很奇怪的問題,@Modifying需要和@Transactional配合使用才能正常使用。如下面代碼所示
@Modifying @Transactional @Query("delete from User u where u.active = false") void deleteInactiveUsers();
為什么@Modifying和@Transactional配合才能使用?首先需要了解@Modifying和@Transactional的作用,@Modifying的主要作用是聲明執行的SQL語句是更新(增刪改)操作,@Transactional的主要作用是提供事務支持(提供例如隔離性等事務特性,JPA默認會依賴JDBC默認隔離級別)。
查閱SpringDataJPA文檔可以看到下面一段話
By default, CRUD methods on repository instances are transactional. For read operations, the transaction configuration readOnly flag is set to true. All others are configured with a plain @Transactional so that default transaction configuration applies. For details, see JavaDoc of SimpleJpaRepository.
這段話的大致意思是默認情況下JPA的每個操作都是事務的,在默認情況下,JPA的事務會設置為只讀,具體可以參考SimpleJpaRepository。
這樣@Modifying和@Transactional為什么配合才能使用的原因就很明顯了,實質上@Modifying只是聲明了這個操作是一個修改操作,但卻沒有修改這個方法的事務等級,因此這個方法依然不能進行修改操作。只有聲明了@Transactional,本質上是聲明了@Transactional(readOnly=false),這樣覆蓋了默認的@Transactional配置便可以執行修改操作了。