{"record":{"id":"09efbfe480429275","repo":"hibernate/hibernate-orm","slug":"no-active-transaction-for-update-or-delete-query","errorCode":null,"errorMessage":"No active transaction for update or delete query","messagePattern":"No active transaction for update or delete query","errorType":"exception","errorClass":"TransactionRequiredException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java","lineNumber":1318,"sourceCode":"\t\treturn factory.getServiceRegistry()\n\t\t\t\t.requireService( ConfigurationService.class )\n\t\t\t\t.getSettings();\n\t}\n\n\tprotected void initializeCurrentChangesetIdentifier() {\n\t\tcurrentChangesetId = generateCurrentChangesetIdentifier();\n\t}\n\n\tprotected void clearTransactionStartInstant() {\n\t\tcurrentChangesetId = null;\n\t\tcurrentChangesetContext = null;\n\t}\n\n\t@Override\n\tpublic void checkTransactionNeededForUpdateOperation(@Nonnull String exceptionMessage) {\n\t\tif ( !factoryOptions.isAllowOutOfTransactionUpdateOperations()\n\t\t\t\t&& !isTransactionInProgress() ) {\n\t\t\tthrow new TransactionRequiredException( exceptionMessage );\n\t\t}\n\t}\n\n\tprivate boolean isTransactionAccessible() {\n\t\t// JPA requires that access not be provided to the transaction when using JTA.\n\t\t// This is overridden when SessionFactoryOptions isJtaTransactionAccessEnabled() is true.\n\t\treturn factoryOptions.isJtaTransactionAccessEnabled() // defaults to false in JPA bootstrap\n\t\t\t|| !factoryOptions.getJpaCompliance().isJpaTransactionComplianceEnabled()\n\t\t\t|| !factory.transactionCoordinatorBuilder.isJta();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Transaction getTransaction() throws HibernateException {\n\t\tif ( !isTransactionAccessible() ) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"Transaction is not accessible when using JTA with JPA-compliant transaction access enabled\"\n\t\t\t);","sourceCodeStart":1300,"sourceCodeEnd":1336,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java#L1300-L1336","documentation":"Same guard as error 1547 (checkTransactionNeededForUpdateOperation), invoked from the bulk-statement path: executeUpdate() on an HQL/SQL/criteria update or delete query requires an active transaction unless hibernate.allow_update_outside_transaction is true. The message here names the caller's context: 'No active transaction for update or delete query'.","triggerScenarios":"session.createMutationQuery(\"update Stock s set ...\").executeUpdate(), createNativeQuery(\"delete from log_table\").executeUpdate(), or criteria update/delete executed while isTransactionInProgress() is false.","commonSituations":"Bulk maintenance/cleanup jobs without @Transactional; test data deletion outside a transaction; refactoring a select query into an update but keeping the non-transactional context; Spring method-level security or AOP ordering hiding the missing transaction.","solutions":["Begin a transaction before executeUpdate(): @Transactional on the method, or session.beginTransaction()/TransactionTemplate.","If you truly want auto-commit bulk DML, set hibernate.allow_update_outside_transaction=true and accept the loss of atomicity.","Check for proxy/self-invocation issues that silently dropped the transaction."],"exampleFix":"// before\nint n = em.createQuery(\"delete from AuditLog a where a.created < :d\")\n          .setParameter(\"d\", cutoff).executeUpdate(); // throws\n// after\n@Transactional\npublic int purgeBefore(Instant cutoff) {\n    return em.createQuery(\"delete from AuditLog a where a.created < :d\")\n             .setParameter(\"d\", cutoff).executeUpdate();\n}","handlingStrategy":"validation","validationCode":"Transaction tx = session.isTransactionInProgress() ? null : session.beginTransaction();\ntry {\n    int n = session.createMutationQuery(\"delete from AuditLog a where a.created < :d\")\n                   .setParameter(\"d\", cutoff).executeUpdate();\n    if (tx != null) tx.commit();\n    return n;\n} catch (RuntimeException e) {\n    if (tx != null) tx.rollback();\n    throw e;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap every executeUpdate() call site in a transactional boundary","Only enable hibernate.allow_update_outside_transaction for deliberate auto-commit DML","Code-review bulk jobs for missing @Transactional after refactors"],"tags":["hibernate","transactions","bulk-update","executeupdate","orm"],"backgroundTag":"transaction-required","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}