Reputation: 473
I have the following code using Spring @Transactional annotation.
//in A.java
Class A {
@Transactional(propagation=propagation.???)
public void aMethod() {
B b = new B();
b.bMethod(); // success and committed
aPrivateMethod(); // failure
}
private void aPrivateMethod() { //something }
}
//in B.java
Class B {
@Transactional(propagation=propagation.???)
public void bMethod() { //something }
}
The behavior I expect of A.aMethod() is:
If b.bMethod() succeeds and has committed but aPrivateMethod() fails, then A.aMethod() is rolled back including b.bMethod().
How can I set the @Transactional propagation parameters to achieve this?
Upvotes: 2
Views: 3707
Reputation: 21
All posted examples will open up a new transaction context irrespective of any outer transactions. Hence REQUIRES_NEW will only work within its transactional block and rollback changes within this scope only. You just need to provide:
Class A {
@Transactional(propagation=Propagation.REQUIRED)
public void aMethod() {
B b = new B();
b.bMethod(); // success and committed
aPrivateMethod(); // failure
}
private void aPrivateMethod() { //something }
}
Upvotes: 0
Reputation: 473
Here's the conclusion.
Example 1
// A.java
class A {
@Transactional(rollbackFor = Exception.class)
public void aMethod() {
B b = new B();
try {
b.bMethod("111", false); // bMethod() is NOT rolled back, record of "111" has been created
} catch (Exception e) {
// Do nothing, let it go
}
b.bMethod("222", true); // record of "222" has been created
}
// The annotation below is ignored
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void bMethod(String id, bool success) {
createRecordInDB(id);
if (!success) {
throw new Exception("Throw exception explicitly!");
}
}
}
Example 2
// A.java
class A {
@Transactional(rollbackFor = Exception.class)
public void aMethod() {
B b = new B();
b.bMethod("111", true); // record of "111" has been rolled back and NOT created
b.bMethod("222", true); // record of "222" has been rolled back and NOT created
createRecordInDB("333"); // record of "333" has been rolled back and NOT created
throw new Exception("Throw exception explicitly!");
}
// The annotation below is ignored
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void bMethod(String id, bool success) {
createRecordInDB(id);
if (!success) {
throw new Exception("Throw exception explicitly!");
}
}
}
Example 3
// A.java
class A {
@Transactional(rollbackFor = Exception.class)
public void aMethod() {
B b = new B();
try {
b.bMethod("111", false); // bMethod() has been rolled back, record of "111" has NOT been created
} catch (Exception e) {
// Do nothing, let it go
}
b.bMethod("222", true); // record of "222" has been created
}
}
// B.java
class B {
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void bMethod(String id, bool success) {
createRecordInDB(id);
if (!success) {
throw new Exception("Throw exception explicitly!");
}
}
}
Example 4
// A.java
class A {
@Transactional(rollbackFor = Exception.class)
public void aMethod() {
B b = new B();
b.bMethod("111", true); // record of "111" has been created
b.bMethod("222", true); // record of "222" has been created
createRecordInDB("333"); // record of "333" has been rolled back and NOT created
throw new Exception("Throw exception explicitly!");
}
}
// B.java
class B {
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void bMethod(String id, bool success) {
createRecordInDB(id);
if (!success) {
throw new Exception("Throw exception explicitly!");
}
}
}
Upvotes: 2