Spring Propagation examples in layman's terms

10,453

PROPAGATION_REQUIRED

class Service {
    @Transactional(propagation=Propagation.REQUIRED)
    public void doSomething() {
        // access a database using a DAO
    }
}

When doSomething() is called it will start a new transaction if the caller has not already started a transaction.

If the caller of this method has already started a transaction then the callers' transaction is used and no new transaction is created (i.e. there is one transaction in play).

If an exception is thrown inside doSomething() then it will be rolled back, meaning that the caller will also see the transaction rolled back.

When doSomething() returns the transaction will not have been commited yet. It is the caller that will commit the transaction (or possibly rolled-back).

PROPAGATION_REQUIRES_NEW

class Service {
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void doSomething() {
        // access a database using a DAO
    }
}

When doSomething() is called it will always start a new transaction.

If the caller of this method has already started a transaction (TxnOuter) then the callers' transaction is suspended and a new transaction (TxnInner) is created (i.e. there are two transactions in play).

If an exception is thrown inside doSomething() then TxnInner will be rolled back, but the "suspended" transaction from the caller (TxnOuter) is unaffected.

When doSomething() returns without an Exception it will commit the transaction (TxnInner). The caller's transaction (TxnOuter) will be resumed and be unaware that another transaction was commited. The caller can then commit or roll-back TxnOuter as it sees fit.

The important point to note is that the Database views TxnOuter and TxnInner as completely independant transactions, and therefore two independant commits.

PROPAGATION_NESTED

class Service {
    @Transactional(propagation=Propagation.NESTED)
    public void doSomething() {
        // access a database using a DAO
    }
}

NESTED can only be used if your JDBC driver and/or database supports JDBC savepoints

When doSomething() is called it will start a new transaction if the caller has not already started a transaction.

If the caller of this method has already started a transaction then the callers' transaction is used and no new transaction is created (i.e. there is one transaction in play). However a "savepoint" is marked on the transaction when doSomething() is entered.

If an Exception is thrown inside doSomething() then the transaction can be partially rolled back the transaction to the "savepoint". The caller will continue with the transaction.

When doSomething() returns without an Exception it is the caller who will commit the entire transaction (or roll back).

The important point to note is that the Database views only one transaction and there is only one commit.

Share:
10,453

Related videos on Youtube

wild_nothing
Author by

wild_nothing

Updated on May 16, 2020

Comments

  • wild_nothing
    wild_nothing about 4 years

    The Spring docs do a fantastic job of describing transactional propagation properties.

    However, I was wondering if there are any well-known, real-world examples available which describe each of these properties more thoroughly in layman's terms?

    • Xstian
      Xstian almost 10 years
      I suggest you this link, it was very useful for me.
    • Brad
      Brad almost 10 years
      People have found my layman's answer (not the accepted answer) about Propagation.REQUIRED useful
    • wild_nothing
      wild_nothing almost 10 years
      Thanks @Brad that's a great answer and exactly what I want. Do you mind expanding on it for the other types of propagation?
  • wild_nothing
    wild_nothing almost 10 years
    This is excellent, Brad. Exactly what I was looking for, thank-you!
  • Amar
    Amar over 9 years
    spring reference seems a bit complicated to understand for first timers. good explanation. simple..
  • Karol Król
    Karol Król about 9 years
    Your answer is a reference pattern how a documentation should be written. Thank you!
  • informatik01
    informatik01 about 9 years
    Nice explanation. But just to avoid confusion, a quote from the section related to Propagation.Required: "When doSomething() returns the transaction will not have been commited yet. It is the caller that will commit the transaction (or possibly rolled-back).". You probably meant IF initially it was a caller's transaction (i.e. NOT new), right? Because in case of a NEW transaction (i.e. created by the annotated function) it must be committed at the end of the function (in case everything went fine).
  • Mubasher
    Mubasher over 8 years
    Although good explaination but I have confusion. when a caller calls doSomething and transaction is caller's transaction. and at some point doSomething raised exception. Now there is doSomething2() method after doSomething(). which is also transactional. My Question: will whole transaction of caller be roolbacked due to exception raised in doSomething() ?
  • Brad
    Brad over 8 years
    Yes @informatik01, you are correct. That sentence relates to the scenario where a Transaction was already started by the caller of doSomething()
  • Brad
    Brad over 8 years
    @Musbasher, that will depend on your Exception handling. If you don't catch the exception from doSomething() then it will bubble up to the caller and rollback the transaction. If you catch and swallow the exception, then the caller will see that everything is fine and try to commit the transaction. I don't know your code so I can't provide an accurate answer. All I can suggest is for you to write a test to see what happens for yourself. If you get stuck post another SO question.
  • dobrivoje
    dobrivoje over 4 years
    I wonder a lot why there isn't more people like @Brad, I mean really, this life would be a lot easier. For me there is a fantastic explanation here : youtu.be/zVRO-LELoSw