<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Ali Sohrabi</title>
        <link>https://virgool.io/feed/@alisohrabi</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 16:16:35</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/40594/avatar/mkcDmn.jpg?height=120&amp;width=120</url>
            <title>Ali Sohrabi</title>
            <link>https://virgool.io/@alisohrabi</link>
        </image>

                    <item>
                <title>Rollback in Hibernate Transactions</title>
                <link>https://virgool.io/@alisohrabi/rollback-in-hibernate-transactions-jv8tkqan2sfi</link>
                <description>Why Some Exceptions Trigger Rollback and Others Don’tOne of the most common sources of bugs in Spring + Hibernate applications is misunderstanding transaction rollback behavior.Many developers assume:“If an exception happens, the transaction will rollback.”That assumption is wrong by default.Let’s clarify how it really works — and how to avoid costly data inconsistencies.The Core Rule (Spring Default)In Spring-managed transactions (@Transactional):🔴 Unchecked Exceptions(RuntimeException, Error)➡ Trigger rollback automatically🟡 Checked Exceptions(Exception, IOException, SQLException)➡ DO NOT trigger rollback by defaultThis rule surprises many developers — especially those new to Spring.Why Does Spring Work This Way?This behavior is intentional and based on Java’s exception philosophy:Checked exceptions→ Often represent recoverable or business-related conditions→ Spring assumes you might want to commit and handle themUnchecked exceptions→ Represent programming errors or system failures→ Spring assumes the transaction is unsafe to commitA Simple Example@Transactional
public void createUserWithCheckedException() throws IOException {
    userRepository.save(new User(&quot;Alice&quot;));
    throw new IOException(&quot;Checked exception&quot;);
}
✅ The user WILL be savedNow compare that with:@Transactional
public void createUserWithRuntimeException() {
    userRepository.save(new User(&quot;Bob&quot;));
    throw new RuntimeException(&quot;Runtime exception&quot;);
}
❌ The transaction WILL rollbackSame code. Different exception type. Very different outcome.Forcing Rollback on Checked ExceptionsYou can explicitly tell Spring to rollback:@Transactional(rollbackFor = IOException.class)
public void createUserSafely() throws IOException {
    userRepository.save(new User(&quot;Charlie&quot;));
    throw new IOException(&quot;Now it rolls back&quot;);
}
This is essential when checked exceptions should indicate transaction failure.Preventing Rollback for Runtime ExceptionsSometimes you want the opposite:@Transactional(noRollbackFor = IllegalStateException.class)
public void processNonCriticalFailure() {
    repository.save(new Entity());
    throw new IllegalStateException(&quot;Non-critical issue&quot;);
}
⚠ Use this carefully — it can be dangerous if misused.Best Practice: Use Runtime Exceptions for Transaction FailuresMost mature Spring applications follow this rule:All exceptions that should rollback a transaction should be uncheckedExample:public class InsufficientBalanceException extends RuntimeException {
    public InsufficientBalanceException(String message) {
        super(message);
    }
}
Why this works well:Clear intentAutomatic rollbackCleaner service layerNo rollbackFor noise everywhereA Common Anti-Pattern (Very Important)❌ Catching exceptions inside a @Transactional method@Transactional
public void badExample() {
    try {
        repository.save(new Entity());
        throw new RuntimeException();
    } catch (Exception e) {
        // swallowed
    }
}
✅ Transaction will commit❌ Data may be inconsistentIf you catch an exception, Spring assumes everything is fine unless you manually mark rollback.Hibernate vs Spring: A Quick NotePure Hibernate (Session API)→ Any exception usually marks the transaction rollbackSpring + Hibernate (most projects)→ Spring rules apply (unchecked only by default)Understanding this difference matters when debugging legacy code.Key Takeaways✅ Unchecked exceptions → rollback (default)⚠ Checked exceptions → commit (default)🔧 Use rollbackFor only when necessary🧠 Prefer unchecked exceptions for transactional failures❌ Don’t swallow exceptions inside transactionsIf you’ve ever seen “ghost data”, partial updates, or unexpected commits — this rule is often the reason.Understanding it once can save hours of debugging later.💬 Have you been bitten by this behavior before?</description>
                <category>Ali Sohrabi</category>
                <author>Ali Sohrabi</author>
                <pubDate>Sun, 28 Dec 2025 17:32:36 +0330</pubDate>
            </item>
            </channel>
</rss>