SpringDataJpa報TransactionRequiredException異常

問題描述

在代碼中利用Jpa自定義了update語句,比如下面的addAge方法:

@Repository
public interface StudentRepository extends JpaRepository<Student, Integer> {

    @Query(value = "update tb_student set age = age + 1 where 1 = 1 ", nativeQuery = true)
    @Modifying
    void addAge();

}

執(zhí)行此方法時,會報如下錯誤:

javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:398) ~[hibernate-core-5.3.11.Final.jar:5.3.11.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1581) ~[hibernate-core-5.3.11.Final.jar:5.3.11.Final]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:263) ~[spring-data-jpa-2.1.10.RELEASE.jar:2.1.10.RELEASE]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91) ~[spring-data-jpa-2.1.10.RELEASE.jar:2.1.10.RELEASE]

拋出javax.persistence.TransactionRequiredException: Executing an update/delete query 異常

原因分析

我們根據(jù)異常中的這句話

at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1581)

找到了AbstractProducedQuery中的executeUpdate方法:

    public int executeUpdate() throws HibernateException {
        getProducer().checkTransactionNeededForUpdateOperation( "Executing an update/delete query" );

        beforeQuery();
        try {
            return doExecuteUpdate();
        }
        catch ( QueryExecutionRequestException e) {
            throw new IllegalStateException( e );
        }
        catch( TypeMismatchException e ) {
            throw new IllegalArgumentException( e );
        }
        catch ( HibernateException e) {
            throw getExceptionConverter().convert( e );
        }
        finally {
            afterQuery();
        }
    }

進(jìn)入第一句話的checkTransactionNeededForUpdateOperation方法:

default void checkTransactionNeededForUpdateOperation(String exceptionMessage) {
    if ( !isTransactionInProgress() ) {
        throw new TransactionRequiredException( exceptionMessage );
    }
}

可以看到,在執(zhí)行update語句前,JPA會判斷當(dāng)前語句是不是處于一個事務(wù)中,若不在事務(wù)中,則會拋出TransactionRequiredException異常。

問題解決

根據(jù)以上分析,要解決這個問題很簡單,讓代碼運行在事務(wù)中即可。在要執(zhí)行的addAge方法上面加上@Transactional注解,問題解決。

@Query(value = "update tb_student set age = age + 1 where 1 = 1 ", nativeQuery = true)
@Modifying
@Transactional
void addAge();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容