Backend Development 8 min read

Master Spring Boot Transaction Management with TransactionTemplate and PlatformTransactionManager

This guide explains Spring Boot's programmatic transaction management using TransactionTemplate, TransactionCallback, and PlatformTransactionManager, covering configuration, rollback handling, event listeners, and when to prefer programmatic versus declarative approaches, complete with code examples.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot Transaction Management with TransactionTemplate and PlatformTransactionManager

Environment: Spring Boot 2.3.9.RELEASE. Spring provides two programmatic transaction management approaches: using TransactionTemplate/TransactionalOperator or directly creating a TransactionManager implementation. Spring recommends the TransactionTemplate method.

Preparation

Entity class Users, repository, mapper and XML snippet are shown.

<code>@Entity
@Table(name="BC_USERS")
@Data
public class Users {
    private String username;
    private String password;
    private Integer status = 0;
}

// DAO
public interface UsersRepository extends JpaRepository<Users, String> {
    @Modifying
    @Query("update Users u set u.status=?1,u.password='123123' where u.id=?2")
    int updateUsers(Integer status, String id);
}

@Mapper
public interface UsersMapper {
    int insertUser(Users user);
}

<!-- Mapper.xml -->
<insert id="insertUser" parameterType="com.pack.domain.Users">
    insert into bc_users (id, username, password) values (#{id}, #{username}, #{password})
</insert>
</code>

1. TransactionTemplate

1.1 With return value

<code>@Service
public class UserService {
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private UsersRepository usersRepository;

    public Integer saveUsers(Users users) {
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus status) {
                return usersMapper.insertUser(users);
            }
        });
        return result;
    }
}
</code>

1.2 Without return value

<code>public void saveUsers(Users users) {
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            usersMapper.insertUser(users);
        }
    });
}
</code>

1.3 Transaction rollback

<code>public Users saveUser(Users users) {
    return transactionTemplate.execute(new TransactionCallback<Users>() {
        @Override
        public Users doInTransaction(TransactionStatus status) {
            try {
                return usersMapper.insertUser(users);
            } catch (Exception e) {
                status.setRollbackOnly();
            }
            return null;
        }
    });
}
</code>

1.4 Configuring transaction attributes

<code>private TransactionTemplate transactionTemplate;

public UserService(PlatformTransactionManager transactionManager) {
    this.transactionTemplate = new TransactionTemplate(transactionManager);
    this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
    this.transactionTemplate.setTimeout(30); // seconds
}
</code>

2. TransactionalOperator

TransactionalOperator is intended for reactive programming; this article does not cover it.

3. TransactionManager

Two main types exist: PlatformTransactionManager for standard Spring applications and ReactiveTransactionManager for reactive contexts (the latter is not discussed here).

3.1 PlatformTransactionManager

<code>private PlatformTransactionManager transactionManager;
private DefaultTransactionDefinition definition;
private TransactionStatus status;
@Resource
private UsersRepository usersRepository;

public UserService3(PlatformTransactionManager transactionManager) {
    this.transactionManager = transactionManager;
    definition = new DefaultTransactionDefinition();
    definition.setName("pgName");
    definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
}

public Integer saveUsers(Users users) {
    TransactionStatus status = this.transactionManager.getTransaction(definition);
    Integer result = null;
    try {
        result = usersMapper.insertUser(users);
    } catch (Exception e) {
        transactionManager.rollback(status);
        throw e;
    }
    transactionManager.commit(status);
    publisher.publishEvent(new UsersEvent(users));
    return result;
}
</code>

4. Transaction Event Listener

Use @TransactionalEventListener to listen to transaction phases such as AFTER_COMMIT, AFTER_ROLLBACK, AFTER_COMPLETION, and BEFORE_COMMIT. This annotation works only with declarative transactions managed by PlatformTransactionManager.

<code>public @interface TransactionalEventListener {
    TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;
    boolean fallbackExecution() default false;
    Class<?>[] value() default {};
    Class<?>[] classes() default {};
    String condition() default "";
}
</code>

The TransactionPhase enum defines the possible phases:

<code>public enum TransactionPhase {
    BEFORE_COMMIT,
    AFTER_COMMIT,
    AFTER_ROLLBACK,
    AFTER_COMPLETION
}
</code>

Example listener component and event publishing code are provided, demonstrating handling of events after commit, after rollback, after completion, and before commit.

Conclusion: Programmatic transaction management is suitable for scenarios with a limited number of transactional operations, such as a single service call that performs extensive calculations before committing once. When many transactional operations are required, declarative transaction management is more appropriate.

Javabackend developmentSpring Boottransaction managementTransactionTemplatePlatformTransactionManager
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.