Common Spring @Transactional Pitfalls and How to Fix Them
This article examines frequent Spring transaction problems—including ineffective transactions, rollback anomalies, and issues when combining read‑write separation with @Transactional—explains their root causes, and provides practical solutions such as engine changes, bean configuration, proxy usage, rollback settings, and proper propagation levels.
Preface
In the previous article we analyzed Spring transactions in detail; this article discusses common problems when using @Transactional in daily work and their solutions.
Transaction ineffective
Transaction rollback issues
Problems when combining read‑write separation with transactions
Transaction Ineffective
We usually investigate the problem from two aspects.
Database Layer
Check whether the storage engine supports transactions. MySQL uses InnoDB by default, which supports transactions, but if the table is altered to MyISAM, transactions become ineffective. alter table table_name engine=myisam; Solution: Change the storage engine back to InnoDB.
Business Code Layer
Ensure the bean is managed by Spring (e.g., annotated with @Service or @Component) and that @Transactional is placed on a public method.
Solution: Add @Service annotation to the bean.
Also, @Transactional must be on a public method; otherwise it is ignored.
Solution: Change the method visibility to public.
Self‑invocation also disables transaction interception because the call bypasses the proxy.
Solution: Inject the bean into itself and call through the proxy, or use AopContext.currentProxy().
@Service
public class DmzService {
@Autowired
DmzService dmzService;
@Transactional
public void save(A a, B b) {
dmzService.saveB(b);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveB(B b) {
dao.saveB(b);
}
}Alternatively, enable proxy exposure and call via AopContext:
@Service
public class DmzService {
@Transactional
public void save(A a, B b) {
((DmzService) AopContext.currentProxy()).saveB(b);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveB(B b) {
dao.saveB(b);
}
}Enable proxy exposure in configuration: @EnableAspectJAutoProxy(exposeProxy = true)
Transaction Rollback Issues
Two typical situations:
Rollback is expected but the transaction commits.
Commit is expected but the transaction is marked rollback‑only.
The first case usually stems from misunderstanding the rollbackFor attribute. By default Spring rolls back only for unchecked exceptions ( RuntimeException) and Error.
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}Solution: Specify rollbackFor = Exception.class (or other checked exceptions) on the @Transactional annotation.
The second case occurs when an inner transaction marks the outer one as rollback‑only. Even if the outer method catches the exception, the transaction cannot be committed.
Solution: Adjust propagation ( REQUIRES_NEW or NESTED) or explicitly set rollback status only when appropriate.
@Transactional
public void testRollbackOnly() {
try {
indexService.a();
} catch (ClassNotFoundException e) {
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
}
}Read‑Write Separation with Transactions
Read‑write separation can be implemented via multiple data sources or middleware such as MyCat.
If multiple data sources are used, a read‑write transaction must use the write node, while a read‑only transaction may use the read node.
When using middleware, any transaction typically forces all SQL to the write node.
Therefore, avoid annotating every service with @Transactional unless necessary, and be careful with the readOnly attribute, which may route reads to the master database and defeat the purpose of read‑write separation.
Summary
This article concludes the series on Spring transactions, summarizing common pitfalls and practical solutions to help developers avoid mistakes.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
