Cause
When you learn spring, you know that AOP has an application that is declarative annotation. Anyway, I lost @transactional on the service and finished. It's easy not to start the hibernate session yourself.
But there are many properties in @transactional that have never been used ... One of the things that I care about most is the propagation property ... Other properties are fine to understand. But this attribute has not been understood, also has not been how to study.
In most cases it is OK to use @transactional without additional setup. Because the default propagation is propagation.required. What does the other propagation do?
The introduction of the Internet is very similar. Just a few simple introductions: Look, I'm still a little dizzy ... So I practiced a bit ... Post the results of the experiment ...
Experimental steps
I have mainly experimented with 3 cases. I think the three kinds of situations are the most easily mistaken ... Other propagation are better understood ...
The specific experimental step was that I wrote 2 nested service. The outside service was propagation.required. The service on the inside was tried propagation.required, Propagation.requires_new and propagation.nested
Note that the outer service uses Trycatch when invoking the internal service. Otherwise an exception will be thrown if the inner layer throws an exception and the outer layers are not processed.
My service looks like this:
1@Transactional (propagation =propagation.required)2 Public voidoperate1 () {3House s =NewHouse ();4S.setname ("841o1");5 Repository.save (s);6 Try{7 Service.operate2 ();8}Catch(Exception e) {9 e.printstacktrace ();Ten } OneHouse S3 =NewHouse (); AS3.setname ("843o1"); - Repository.save (S3); - Throw Newruntimeexception (); the}
1 @Transactional (propagation = propagation.nested)2public void Operate2 () {3 new House (); 4 S.setname ("842o2"); 5 Repository.save (s); 6 // throw new RuntimeException (); 7 }
Process is external service Save Object 1, Inside Service Save Object 2, external service Save Object 3
Experimental results
|
The outer service throws an exception |
The inner service throws an exception |
The inner service is propagation.required |
Object-All-in-a-roll rollback |
Object-All-in-a-roll rollback |
The inner service is propagation.requires_new |
Object 1, 3 rollback, 2 successful commit |
Object 1,3 submitted successfully, 2 rollback |
The inner service is propagation.nested |
Object-All-in-a-roll rollback |
Object 1,3 submitted successfully, 2 rollback |
Conclusion
Propagation.required: Internal and external transactions can be considered to be the same transaction, commit together, or rollback together.
Propagation.requires_new: Internal and external transactions are completely unrelated, that is, 2 transactions
propagation.nested: Outer transaction commit inner transaction is possible commit, outer transaction rollback inner transaction must rollback. The outer transaction commits, and the inner transaction may still be rollback
Other than that:
When I propagation.nested with the Spring data JPA experiment, I was prompted that JPA implementations (hibernate) did not support savepoint.
I can do it directly with hibernate. But to set the Nestedtransactionallowed property of Org.springframework.orm.hibernate4.HibernateTransactionManager to True
Spring Learning record [email protected] propagation