You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The @Modifying annotation is used for INSERT, UPDATE, DELETE, and table structure modification operations. In most cases, such operations require transactional support to ensure:
Data consistency.
Protection against incorrect execution when the method is invoked within a readOnly transaction.
Safe execution of operations in cases of errors or exceptions.
Currently, @Modifying does not automatically enforce a transactional context, leading to several issues:
When the method is invoked within a readOnly transaction, errors can occur (e.g., cannot execute statement in read-only transaction).
Developers must explicitly add the @Transactional annotation to every method, resulting in repeated boilerplate code.
In large projects, there is a risk of forgetting to add transactional support, which can cause unexpected behavior or be difficult to debug.
Proposal
Add transactional support to the @Modifying annotation by introducing the following changes:
New transactional Parameter in @Modifying:
Type:boolean
Default value:true (i.e., transactional support enabled by default).
This allows developers to explicitly specify when a transaction is not needed, while keeping the default behavior transactional for most cases.
Example:
@Modifying(transactional = true)
publicvoidupdateEntity(Entityentity) {
// Update data
}
@Modifying(transactional = false)
publicvoidcreateIndex() {
jdbcTemplate.execute("CREATE INDEX idx_name ON table_name (column_name)");
}
Integration with @Transactional:
When transactional = true, the @Modifying annotation should implicitly add behavior equivalent to @Transactional(readOnly = false).
Atomicity Enforcement:
Even for "atomic" operations (e.g., single UPDATE or DELETE), transactional support is beneficial as it:
Provides protection against potential conflicts or errors.
Standardizes behavior and makes the codebase more predictable.
Reasons for the Change
Ensures Safe Transactional Execution:
Avoids situations where a method with @Modifying is invoked within a readOnly transaction, leading to errors or incorrect behavior.
Reduces Boilerplate Code:
Developers will no longer need to manually add @Transactional(readOnly = false) to every method using @Modifying.
Improves Standards:
By default, transactions will be active since the cases requiring transactions significantly outnumber those where they are not needed.
Flexibility:
The additional transactional = false parameter allows for handling rare cases where transactional support is unnecessary (e.g., DDL operations or externally managed transactions).
petro-zhylenko
changed the title
Add Transactional Support to the @Modify Annotation
Add Transactional Support to the @Modifying Annotation
Jan 8, 2025
petro-zhylenko
added a commit
to petro-zhylenko/spring-data-jpa
that referenced
this issue
Jan 9, 2025
Add ModifyingTransactionAspect for conditional transactional support.
Description
Introduced an aspect to handle methods annotated with @Modifying in Spring Data JPA. The aspect checks the transactional parameter in the annotation to decide whether to open a new transaction explicitly.
Added logic to handle transaction management using PlatformTransactionManager.
Includes support for both transactional and non-transactional method executions.
Updated the class-level documentation to explain its purpose, usage, and dependencies.
This improvement allows developers to gain fine-grained control over transactional behavior for @Modifying queries.
References
Related tickets: spring-projects#3733.
Modifying queries do not enforce transactions because we cannot generally assume that a transaction is required. Annotation-enabled transactions are handled by Spring's Aspects and therefore these aren't integrated with meta-annotations that could enable or disable transactions. If you require transaction support for your modifying queries then we recommend creating a meta-annotation on your side that is configured with your project-specific needs.
The purpose of @Modifying is to use Query.executeUpdate() result count and optionally invoke flush and clear on EntityManager. As general rule of thumb, you should not rely on transactional annotations on the repository but rather run your unit of work in a transaction so that you control the transactional scope.
Problem
The
@Modifying
annotation is used forINSERT
,UPDATE
,DELETE
, and table structure modification operations. In most cases, such operations require transactional support to ensure:readOnly
transaction.Currently,
@Modifying
does not automatically enforce a transactional context, leading to several issues:readOnly
transaction, errors can occur (e.g.,cannot execute statement in read-only transaction
).@Transactional
annotation to every method, resulting in repeated boilerplate code.Proposal
Add transactional support to the
@Modifying
annotation by introducing the following changes:New
transactional
Parameter in@Modifying
:boolean
true
(i.e., transactional support enabled by default).This allows developers to explicitly specify when a transaction is not needed, while keeping the default behavior transactional for most cases.
Example:
Integration with
@Transactional
:When
transactional = true
, the@Modifying
annotation should implicitly add behavior equivalent to@Transactional(readOnly = false)
.Implementation Example:
Atomicity Enforcement:
Even for "atomic" operations (e.g., single
UPDATE
orDELETE
), transactional support is beneficial as it:Reasons for the Change
Ensures Safe Transactional Execution:
Avoids situations where a method with
@Modifying
is invoked within areadOnly
transaction, leading to errors or incorrect behavior.Reduces Boilerplate Code:
Developers will no longer need to manually add
@Transactional(readOnly = false)
to every method using@Modifying
.Improves Standards:
By default, transactions will be active since the cases requiring transactions significantly outnumber those where they are not needed.
Flexibility:
The additional
transactional = false
parameter allows for handling rare cases where transactional support is unnecessary (e.g., DDL operations or externally managed transactions).Examples of Use
1. Default Transactional Method:
2. Non-Transactional Method (DDL Operation):
3. Invocation Within a Read-Only Transaction:
Expected Outcome
readOnly
transactions.Additional Steps
Update the documentation for
@Modifying
to include the newtransactional
parameter and provide guidance on when to use it.The text was updated successfully, but these errors were encountered: