@Transactional

 



@Transactional


When You Use @Transactional at the Class Level:

All public methods of the class are automatically transactional, as if you had added @Transactional on each method.


Public method  ==> Runs within a transaction                                           

Private / protected method  ==>  Not transactional (no proxy interception)                        

Internal method call  ==>  Not transactional (e.g., calling one method from another within same class) 

Spring AOP-based proxy  ==> Only public methods are proxied and eligible for transaction management  


With Proxy (via @Transactional): Spring creates this proxy automatically when you use @Transactional.

userService.updateUser(); 

Goes through proxy first:

        1. Start Transaction

        2. Call real method

        3. Commit or Rollback Transaction


Without Proxy (without @Transactional): 

userService.updateUser(); 

Directly runs the real updateUser() method


Case 1: methodA() and methodB() are in the same class

@Service
public class UserService {
@Transactional
public void methodA() {
// DB queries
methodB(); // self-invocation
// DB queries
}

@Transactional
public void methodB() {
// DB queries
}
}


TransactionA is opened when methodA() is called.

All DB queries inside methodA() are executed inside TransactionA.

methodB() is called directly, NOT via proxy, so its @Transactional is ignored.

Therefore, methodB() also runs inside TransactionA.

The entire thing — methodA() and methodB() — commit or roll back together.


Case 2: methodB() is in another class (ServiceB)

@Service
public class ServiceB {
@Transactional
public void methodB() {
// DB queries
}
}

@Service
public class UserService {
@Autowired
private ServiceB serviceB;

@Transactional
public void methodA() {
// DB queries
serviceB.methodB(); // cross-bean call
// DB queries
}

}

methodA() starts TransactionA.

All queries before serviceB.methodB() are part of TransactionA.

Now it depends on transaction propagation:

If methodB() has @Transactional(propagation = Propagation.REQUIRED) (default):

It joins TransactionA, doesn't create a new one.

So methodB() runs in the same transaction as methodA.

Both can be rolled back together.


If methodB() has @Transactional(propagation = Propagation.REQUIRES_NEW):

@Service
public class ServiceB {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// DB queries
}
}

A new transaction (TransactionB) is started.

Now methodB runs in a separate transaction.

It commits or rolls back independently of methodA.




-----------------------



Think about DB transaction and hibernate.

In DB side. Normally when we open transaction and then do some changes. DB row is loaded to RAM and our changes applied to it. Those are not updated to DB until we commit and completed the transaction.
In hibernate, we can use @Transaction annotation to handle the above behavior.
If we annotated a method @Transaction, then all the update or delete we done in method are not committed to DB Until method close or complete the transaction. 
Once Transaction complete, data will save in DB permanently.
Until saving updated or deleted data hold in same where (In SQL, it is on RAM)... In hibernate, is it use the SQL server RAM or application level cache (RAM which application run) ?


 Database Side (SQL Server / MySQL / Postgres, etc.)

 When you begin a transaction:
  •    The DB loads the row from disk into its own memory (RAM) — this is DB server RAM, not your app.
  •    Any updates or deletes are held in a transaction log (Write-Ahead Log) inside the DB.
  •    These changes are not visible to other transactions (unless isolation level allows).
  •    The DB only applies the changes to disk (permanently) when you commit the transaction.

---
Hibernate / Spring Boot Side

When you use:

@Transactional
public void updateData() {
   // fetch, update entity
}


Here’s what happens:

 1. Persistence Context is Created

 Hibernate opens a Persistence Context (aka first-level cache).
 All entities you 'find()' or 'save()' are stored in this context (in application RAM).

 2. Changes Are Tracked in Application Memory

 You update the entity (e.g., 'student.setName("Updated")')
 Hibernate tracks this change in the Persistence Context (RAM of your app).
 It doesn't send an SQL 'UPDATE' immediately.

 3. On Transaction Commit

 Hibernate flushes the changes: generates SQL (e.g., 'UPDATE ...')
 It sends those SQL statements to the DB.
 Then Spring commits the transaction → DB commits → changes written to disk.




Comments

Popular posts from this blog

Database - Topics

02. Spring – Creating spring project clone it with GIT step by step.

01. Steps in SQL Query Execution (MySQL)