Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to solve the multiple situations in which spring declarative transaction @ Transactional does not roll back

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is about how to solve multiple situations where spring declarative transactions @ Transactional do not roll back. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

I. the principle of spring transaction

I. the principle of Spring transaction

When using JDBC transactions to manipulate the database, the process is as follows:

/ / get connection 1.Connection con = DriverManager.getConnection () / / Open transaction 2.con.setAutoCommit (true/false); 3. Execute CRUD// commit transaction / rollback transaction 4. Con.commit () / con.rollback (); / / close connection 5. Conn.close ()

Spring itself does not provide transactions, but encapsulates JDBC transactions through AOP, hides the operations of 2 and 4, and simplifies the application of JDBC.

Spring encapsulates JDBC transactions through AOP dynamic proxies, which perform transaction opening, commit or rollback operations before and after calling the target method (that is, step 3).

Two non-negligible points used by spring transactions:

Note the keyword "dynamic proxy", which means that to generate a proxy class, we cannot call a transaction method directly within a class, otherwise we cannot proxy, and the transaction method must be public, which cannot be called if defined as protected, private, or default visibility!

Question 1. Where should @ Transactional be added, and will it be rolled back if added to Controller?

@ Transactional is best added to the service layer, and it is also valid to add to the Controller layer, but for the sake of specification, it is added to the service layer.

Download the code and start the difficult project for verification: the main code is as follows:

The Controller layer code is as follows:

@ Autowired private TransactionalService transactionalService; @ Autowired private UserDao userDao; @ Autowired private JwtUserDao jwtUserDao; / * Test whether the @ Transactional annotation added to the service-tier transaction is rolled back * / @ RequestMapping ("/ tx") public void serviceTX () {transactionalService.controllerTX () } / * Test whether the @ Transactional annotation added to the Controller-tier transaction is rolled back * / @ Transactional (rollbackFor = Exception.class) @ RequestMapping ("/ ctx2") public void cTX2 () {userDao.update (); System.out.println (2max 0); jwtUserDao.update () } / * Test whether the @ Transactional annotation is added to the Controller layer transaction is rolled back * here the dao layer is called directly in the Controller layer for convenience. In actual development, the dao layer can be called either in the Controller layer or in the service layer. * for example, the service layer only calls a method in the dao layer directly without any operation, so there is no need to write the method in the service layer at this time, you can call the dao layer directly in Controller * of course, if the company has specifications and must strictly follow the mvc model for development, then say * / @ Transactional (rollbackFor = Exception.class) @ RequestMapping ("/ ctx2") public void cTX2 () {userDao.update () / / manually throw a RuntimeException System.out.println (2Accord 0); jwtUserDao.update ();}

The main code of the service layer

@ Autowired private UserDao userDao; @ Autowired private JwtUserDao jwtUserDao; @ Transactional (rollbackFor = Exception.class) public void controllerTX () {userDao.update (); / / manually throw a RuntimeException System.out.println (2max 0); jwtUserDao.update ();}

The dao layer sql statement is as follows:

UPDATE jwt_user SET username = 'wangwuupdate' WHERE user_id= 2 UPDATE user SET username =' zsupdate' WHERE id= 2

Database raw data:

Enter: http://localhost:8081/tx/tx in the browser. Since the test code is used for unified exception handling this time, the returned data of the browser is as follows:

The console output is as follows:

Check that the data in the database has not been modified

Enter: http://localhost:8081/tx/ctx2 in browser

Check that the data in the database has not been modified

It can be concluded that the addition of @ Transactional to the Controller layer is also valid, but for the sake of specification, it is added to the service layer.

Question 2. Do you need to add the attribute value of rollbackFor = Exception.class in the @ Transactional annotation?

Spring's api doc has a description of torture:

The contents in the red box are as follows

Rolling back on RuntimeException and Error but not on checked exceptions

Generally speaking, by default, transactions will be rolled back when RuntimeException and Error exceptions occur in the program, but if checkedExcetions occurs, such as fileNotfundException, the transaction will not be rolled back, so rollbackFor = Exception.class must be added!

Verify as follows:

Browser input: http://localhost:8081/tx/ctx3

The console output is as follows:

At this time, check that the data in the database has not been modified.

Browser input: http://localhost:8081/tx/ctx4

At this point, check that the database data has been modified:

Question 3: the specific result of the nesting problem of transaction calls is as follows: / * * in the same class, calling b * an in method a has no transaction, b has, and the exception occurs in b will not be rolled back * / @ RequestMapping ("/ A1") public void A1 () {transactionalService.a1 () } / * in the same class, calling b * an in method a has no transaction. If an exception occurs in a, it will not roll back * / @ RequestMapping ("/ a2") public void a2 () {transactionalService.a2 () } / * in the same class, calling b * an in method a has a transaction, but b does not. If an exception occurs in b, it will be rolled back * / @ RequestMapping ("/ A3") public void A3 () {transactionalService.a3 () } / * in the same class, calling b * an in method a has a transaction, but b does not. If an exception occurs in a, it will roll back * / @ RequestMapping ("/ A4") public void A4 () {transactionalService.a4 () } / * in the same class, calling b * an in method a has transactions, and b also has transactions. If an exception occurs in b, it will roll back * / @ RequestMapping ("/ A5") public void a5 () {transactionalService.a5 () } / * in the same class, calling b * an in method a has transactions, and b also has transactions. If an exception occurs in a, it will roll back * / @ RequestMapping ("/ A6") public void a6 () {transactionalService.a6 () } / * a class calls methods in class b * a has transactions, and b also rolls back * * / @ RequestMapping ("/ b5") public void b5 () {transactionalService.b5 () } / * a class calls methods in class b * a has a transaction, but there is no rollback in b * * / @ RequestMapping ("/ b6") public void b6 () {transactionalService.b6 () } / * a class calls methods in class b * a has no transaction, and * * / @ RequestMapping ("/ b7") public void b7 () {transactionalService.b7 () is not rolled back in b } / * a class calls methods in class b * a has no transaction, and there is no non-rollback in b * * / @ RequestMapping ("/ b8") public void b8 () {transactionalService.b8 ();}

If the b method is called in the a method, no matter whether an and b are in the same class or not, as long as there is no transaction in the a method, the exception will not be rolled back, that is, when a has no transaction, then both an and b have no transaction, when a has a transaction, b if there is a transaction, then b transaction will be added to a transaction, both of them are the same transaction!

Thank you for reading! This is the end of the article on "how to solve the problem of multiple situations in which spring declarative transactions @ Transactional do not roll back". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report