美文网首页
SpringDataJpa报TransactionRequire

SpringDataJpa报TransactionRequire

作者: 宁静的猫 | 来源:发表于2020-06-07 08:23 被阅读0次

    问题描述

    在代码中利用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();
    
    }
    

    执行此方法时,会报如下错误:

    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 异常

    原因分析

    我们根据异常中的这句话

    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();
            }
        }
    

    进入第一句话的checkTransactionNeededForUpdateOperation方法:

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

    可以看到,在执行update语句前,JPA会判断当前语句是不是处于一个事务中,若不在事务中,则会抛出TransactionRequiredException异常。

    问题解决

    根据以上分析,要解决这个问题很简单,让代码运行在事务中即可。在要执行的addAge方法上面加上@Transactional注解,问题解决。

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

    相关文章

      网友评论

          本文标题:SpringDataJpa报TransactionRequire

          本文链接:https://www.haomeiwen.com/subject/nmmqtktx.html