Spring Transaction Management

📢 This article was translated by gemini-3-flash-preview

Transactions

A transaction is a set of operations that form an indivisible unit of work. These operations either all succeed together or all fail together.

Operations:

  • Start Transaction: Begin the set of operations. (start transaction / begin)
  • Commit Transaction: Finalize the operations if all succeed. (commit)
  • Rollback Transaction: Revert all operations if any step fails. (rollback)

Assume you need to delete a department and then delete all employees in that department:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    
    @Override
    public void delete(Integer id{
        // 1. Delete department
        deptMapper.delete(id);
        
        // If an error occurs here, the department is deleted but employees remain
        
        // 2. Delete employees under this department id
        empMapper.deleteByDetId(id);
    }
}         

In the example above, you’d end up with employees belonging to a non-existent department, causing data inconsistency.

Spring Transaction Management

Annotation: @Transactional.
Placement: Service layer methods, classes, or interfaces.

What it does: Hands over the method to Spring for transaction management. It starts a transaction before execution, commits upon successful completion, and rolls back if an exception occurs.

Updated method:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    
    @Transactional // Managed by Spring
    @Override
    public void delete(Integer id{
        // 1. Delete department
        deptMapper.delete(id);
        
        // 2. Delete employees under this department id
        empMapper.deleteByDetId(id);
    }
}

You can also enable transaction logs in your configuration:

1
2
3
4
# Spring transaction management logs
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

Transaction Attributes - Rollback

By default, Spring only rolls back for RuntimeException. Use the rollbackFor attribute to specify which exception types should trigger a rollback.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    
    // Rollback for all exceptions
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Integer id{
        // 1. Delete department
        deptMapper.delete(id);
        
        // 2. Delete employees under this department id
        empMapper.deleteByDetId(id);
    }
}         

Transaction Attributes - Propagation

Transaction propagation defines how a transaction behaves when one transactional method calls another.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Transactional
public void a(){
    // code
    userServices.b();
    // code
}

@Transactional
public void b(){
    // code
}

When a calls b, propagation determines whether b joins a’s transaction or starts its own.

This is controlled via the propagation attribute:

Attribute ValueDescription
REQUIRED (Default)Requires a transaction. Joins existing if present; creates new if not.
REQUIRES_NEWAlways creates a new transaction, suspending the existing one if present.
SUPPORTSSupports transaction. Joins if present; runs without transaction if not.
NOT_SUPPORTEDDoes not support transaction. Suspends existing; runs without transaction.
MANDATORYMust have an existing transaction, otherwise throws an exception.
NEVERMust not have a transaction, otherwise throws an exception.

Example usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Transactional
public void a(){
    // code
    userServices.b();
    // code
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void b(){
    // code
}