๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
2026-03-01 09:15:22.410 ERROR 8842 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: javax.persistence.TransactionRequiredException: Executing an update/delete query] with root cause
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.query.sql.internal.NativeQueryImpl.doExecuteUpdate(NativeQueryImpl.java:309)โก Quick Fix Works 80% of the time
Add @Transactional and @Modifying annotations to your repository or service method.
@Transactional
@Modifying
@Query("UPDATE User u SET u.status = :status")
void updateStatus(@Param("status") String status);๐ง Why this Happens
Tap to expand the deep technical explanation
JPA and Hibernate strictly enforce that any operation modifying the database (INSERT, UPDATE, DELETE) must occur within a transaction. If you attempt to execute a modifying query without an active transaction context, Hibernate throws this exception to prevent silent, uncommittable data changes.
The HITEC City Parking Spot Analogy:
Imagine trying to withdraw money from a bank account, but the bank hasn't opened the vault yet. The teller (Hibernate) refuses to process the transaction because the secure environment (Transaction) isn't established.
๐ How to Reproduce Confirm this is your error
Call an @Modifying repository method (an update/delete JPQL query) from a service method without @Transactional. Hibernate throws TransactionRequiredException: Executing an update/delete query.
๐ ๏ธ Solutions (3 Ways to Fix)
Add @Transactional to the method
๐ Use this when executing UPDATE or DELETE JPQL/SQL queries.
Hibernate requires an active database transaction to modify data. Without @Transactional, Spring doesn't open a transaction, and Hibernate rejects the query.
@Service
public class UserService {
@Transactional // Add this
public void updateStatus(Long id, String status) {
userRepository.updateStatus(id, status);
}
}Add @Modifying to the Repository
๐ Use this if you are using a custom @Query for UPDATE/DELETE in your Spring Data JPA repository.
Spring Data JPA needs to know that your @Query alters data so it can execute it correctly. @Modifying tells Spring to treat it as an update operation.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Modifying
@Transactional
@Query("DELETE FROM User u WHERE u.active = false")
void deleteInactiveUsers();
}Check for proxy bypass (Self-Invocation)
๐ Use this if you added @Transactional but it still throws the error.
If you call a @Transactional method from another method in the SAME class, Spring's AOP proxy is bypassed, and the transaction is never started. Move the method to a different bean.
// BAD: Called from same class, @Transactional ignored
public void batchUpdate() {
this.updateOne(); // Proxy bypassed!
}
// GOOD: Inject the bean into itself
@Autowired
private UserService self;
public void batchUpdate() {
self.updateOne();
}๐ Version Notes
Uses javax.persistence.TransactionRequiredException.
Uses jakarta.persistence.TransactionRequiredException.
๐ก๏ธ How to Prevent This Next Time
Always annotate service methods that modify data with @Transactional. Use @Modifying on custom Spring Data JPA update/delete queries.