[Solved] Connection is read-only. Queries leading to data modification are not allowed There are two ways to solve the problem

  • 1. One case is caused by adding @Transactional(readOnly = true) to the class in the implementation class,
  •  In this case, you can annotate the method name with @Transactional(readOnly = false)
    
  • 2. See if there is aop unified transaction processing in your framework
  •  restricts transactions starting with individual method names. I use the method starting with resume, which is an error at that time. When the method name starting with resume is added, it is solved. For details, see the figure below.
    
 @Aspect
@Component
public class TransactionAdviceConfig {<!-- -->

    /**
     * Multiple pointcut expressions use and
     */

    private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.test.*.service.impl.*.*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Bean
    public TransactionInterceptor txAdvice() {<!-- -->

        /**
         * Transactions have the following common properties:
         *
         * read-only: Set whether data modification is allowed in this transaction. (For transactions that only execute query functions, setting to TRUE can improve the execution speed of transactions)
         *
         * propagation: The propagation mechanism of the transaction. Generally set to required. Code in a transaction is guaranteed to run only in the current transaction, preventing the creation of multiple transactions.
         *
         * isolation: transaction isolation level. Not required. The default value is default.
         *
         * timeout: The maximum time a transaction is allowed to run, in seconds.
         *
         * rollback-for: The exception that triggered the rollback.
         *
         * no-rollback-for: An exception that will not trigger rollback.
         *
         * In actual development, for transactions that only execute the query function, set read-only to TRUE, and other properties generally use the default values.
         **/
        // transaction propagation behavior
        DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        // read only transaction
        DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
        txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txAttr_REQUIRED_READONLY.setReadOnly(true);

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        source.addTransactionalMethod("remove*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("delete*", txAttr_REQUIRED);
        source.addTransactionalMethod("insert*", txAttr_REQUIRED);
        source.addTransactionalMethod("create*", txAttr_REQUIRED);
        // I wrote it here
        source.addTransactionalMethod("resume*", txAttr_REQUIRED);
        source.addTransactionalMethod("pause*", txAttr_REQUIRED);
        source.addTransactionalMethod("change*", txAttr_REQUIRED);

        /*Use the method named at the beginning of the following characters to enable read-only mode and improve database access performance*/
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("select*", txAttr_REQUIRED_READONLY);
 

        return new TransactionInterceptor(transactionManager, source);
    }

    @Bean
    public Advisor txAdviceAdvisor() {<!-- -->
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}