Xiao Ming : handsome young man , I've encountered something very evil recently .

handsome young man : Oh ? Tell me .

Xiao Ming : Last time I read your article 《 Is this ? An article for you to understand Spring Business 》, Have a detailed understanding of affairs , But there are still problems in the project , Clearly added transaction notes @Transactional, It didn't work .

handsome young man : Today, I'll give you a summary of what scenarios will fail .

1、 The database engine does not support transactions

Mysql Common database engines are InnoDB and MyISAM, Among them, the former supports transaction , The latter does not support ,MySQL 5.5.5 The previous default storage engine was :MyISAM, Previous versions default to :InnoDB , So be sure to note that the database you use does not support transactions .

2、 Has not been Spring management

The class of the transaction method is not injected Spring Containers , Like the following :

public class OrderServiceImpl implements OrderService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper; @Transactional
@Override
public void placeOrder() {
// A bunch of logic is omitted here // The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
}
}

This class does not add @service annotation , The transaction will not take effect .

3、 No public Method

The official documents have made it clear ,@Transactional Annotations can only be used for public Method , If it is to be used in non public On the way , Can be opened AspectJ The proxy pattern .

4、 Exception caught

Here's an example :

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper; @Transactional
@Override
public void placeOrder() {
try{
// A bunch of logic is omitted here // The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
} catch (Exception e) { }
}
}

When an exception occurs in this method , Because the exception was caught , It's not thrown out , So the transaction will fail , How to solve this situation ? Don't worry. , To look down

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper; @Transactional
@Override
public void placeOrder() {
try{
// A bunch of logic is omitted here // The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
} catch (Exception e) {
// Manual rollback
TransactionAspectSupport.crrentTransactionStatus().setRollbackOnly();
}
}
}

Can pass

TransactionAspectSupport.crrentTransactionStatus().setRollbackOnly();

Roll back manually .

5、 Wrong exception type

@Transactional Annotation only rolls back by default RuntimeException Exception of type , Therefore, it is suggested to modify it to Exception type

@Transactional(rollbackFor = Exception.class)

6、 Call the transaction method internally

This should be the most common scenario of transaction failure , That's what I want to focus on .

Some operations with complex business logic , For example, the ordering method in the previous example , There is often a pile of logic before the write operation , If all operations are put in one method , And add transactions , It is likely that the transaction will take too long to execute , Cause transaction timeout , Even if there is no timeout, it will affect the performance of the single interface . At this time, the write operation can be extracted , Add transactions only to write operations , Then the pressure will be much less .

Please see the following example :

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper; @Override
public void placeOrder() {
// A bunch of logic is omitted here
this.updateByTransactional();
} @Transactional
public void updateByTransactional() {
// The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
}
}

Due to an internal call , Without going through Spring Agent for , The transaction will not take effect , It is also stated in the official documents :

What should I do in this case ?

Scheme 1 : Change to external call

Internal calls are not allowed , I'll just call the external call instead

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
OrderTransactionService orderTransactionService; @Override
public void placeOrder() {
// A bunch of logic is omitted here orderTransactionService.updateByTransactional();
}
} @Service
public class OrderTransactionService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper; @Transactional
public void updateByTransactional() {
// The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
}
}

This is an easy way to understand

Option two : Use programmatic transactions

Since declarative transactions are problematic , Then it's OK for me to change to programmatic transactions ?

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper;
@Autowired
TransactionTemplate transactionTemplate; @Override
public void placeOrder() {
// A bunch of logic is omitted here // TransactionCallbackWithoutResult No return parameter
// TransactionCallback There are return parameters
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
this.updateByTransactional();
} catch (Exception e) {
log.error(" Order failure ", e);
transactionStatus.setRollbackOnly();
}
}
});
} public void updateByTransactional() {
// The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
}
}

Never mind his black cat and white cat , A good cat catches a mouse

Option three : Call it back through external methods

This is a method I saw provided by netizens , I want to use annotations again , And I want to call myself , Then you can refer to the way of programmatic transaction to realize .

@Component
public class TransactionComponent {
public interface Callback<T>{
T run() throws Exception;
} public interface CallbackWithOutResult {
void run() throws Exception;
} // With return parameters
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Nullable
public <T> T doTransactional(Callback<T> callback) throws Exception {
return callback.run();
} // No return parameter
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Nullable
public void doTransactionalWithOutResult(CallbackWithOutResult callbackWithOutResult) throws Exception {
callbackWithOutResult.run();
}
}

This way TransactionComponent Call internal method , The failure problem can be solved .

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
AccountMapper accountMapper;
@Autowired
ProductMapper productMapper;
@Autowired
TransactionComponent transactionComponent; @Override
public void placeOrder() {
// A bunch of logic is omitted here transactionComponent.doTransactionalWithOutResult(() -> this.updateByTransactional());
} public void updateByTransactional() {
// The repair user changes the balance and commodity inventory
accountMapper.update();
productMapper.update();
}
}

summary

This paper summarizes several common transaction failure scenarios , And some solutions , It doesn't have to be complete . What other scenes did you encounter that I didn't mention , Welcome to share , There are shortcomings , You are welcome to correct .

END

Previous recommendation

Is this ? An article for you to understand Spring Business

SpringBoot+Redis Implement message subscription and publication

The most detailed graphic analysis Java Various locks ( The ultimate )

Common code refactoring skills , You must be able to use

Graphic, 23 Design patterns

Is this ?Spring More articles on transaction failure scenarios and solutions

  1. Spring The reason why the transaction failed

    http://blog.csdn.net/paincupid/article/details/51822599 Spring The reason why the transaction failed 5 A big reason If you use mysql And the engine is MyISAM, Then the business meeting ...

  2. Spring Transaction invalid 2 In this case

    Use the default transaction mode Because in java In the design of , It holds that it does not inherit RuntimeException The exception is ”checkException” Or ordinary abnormality , Such as IOException, These anomalies are java Grammar requires ...

  3. java Interview record 2 :spring Loading process 、springmvc Request flow 、spring Transaction failure 、synchronized and volatile、JMM and JVM Model 、 The implementation of binary search 、 Garbage collector 、 Console sequential printing ABC Three thread implementations

    notes : Some answers cite online articles Short answer 1.Spring Loading process after project startup (1) Use spring Framework of the web project , stay tomcat Next , It's based on web.xml To start the .web.xml Is responsible for configuring startup spring ...

  4. Spring Transaction invalid 8 The big reason , This time we can hang the interviewer !

    Another one today < Condole interviewer > series , This time it's really going to be a sling fight , ha-ha !( Look at the previous hanging dozen series, please reply in the background : To hang up , I'll keep updating --) A few days ago, the manager didn't post an article , There's a problem with transaction failures : use Spring ...

  5. spring Transaction failure analysis

    See :http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt113 <!--[if !supportLists]--> One .&l ...

  6. Spring In depth analysis of transactions --spring The reason why the transaction failed

    The call of distributed transaction we talked about before is in a service Transaction methods in , To call another service Business methods in , If in a sevice There are two distributed transaction methods in , In a seivice Two transaction methods are nested in each other ...

  7. Spring Transaction failure

    Isolation level stay TransactionDefinition.java Interface , Defined " Four kinds of " Enumeration of isolation levels : /** * [Spring alone possess ] Use the default isolation level of the back-end database * * ...

  8. Mysql Caused by the spring Transaction failure

    Add new functions to old projects , Lead to a service call service The situation of .. altogether 2 Adding and deleting data in this table . Then I tested the transaction , surface A And table B, I'm watching B Threw an exception in , But it turns out , surface B Rollback is normal , But the table A There is no rollback . According to the transaction ...

  9. spring Transaction failure

    Recently doing spring It is suddenly found in the project that the transaction is not rolled back but committed when it encounters an exception , After checking a lot of information , I have a little clue , Write it down so that you can find it later : Some days ago, a friend called himself in the target object , And the corresponding transactions need to be implemented ...

  10. @Transactional spring Transaction failure ( Reprint )

    Original address :http://hwak.iteye.com/blog/1611970 1. Add... Where business management is needed @Transactional annotation .@Transactional Annotations can be applied to interface definitions and ...

Random recommendation

  1. oracle Query month difference

    select to_char(add_months(trunc(sysdate),-1),'yyyymm') from dual;

  2. A few code snippets - Calculate program run time + Get the current directory + Generate MD5

    Calculate program run time long startTime = System.currentTimeMillis(); System.out.println(" Program running time : " + (Sys ...

  3. Android SDK And ADT Solution to update access problem

    One . Interview questions Eclipse Use SDK Manager There are always problems when updating Failed to fetch URL https://dl-ssl.google.com/android/repository ...

  4. 【 turn 】shell:date Commonly used way

    stay linux Get the time string under command date # With yyyymmdd Format output 23 Days ago, at this moment $ date +%Y%m%d –date=’23 days ago’ $ date -u Th ...

  5. The latest podcast web The front-end development 39 Period video tutorial 【 Full version 】

    This set of videos is about Chuanzhi 2018web Front end development of a full set of video tutorial basic class + Employment class , video + Source code + Case notes , Full HD without encryption ~2018 The latest podcast video ! This course is a practical course ! For the latest transmission of wisdom web front end 39 period , Challenge the most complete video of the whole network , No, ...

  6. 《Head First Design patterns 》 Annotation series ( One )—— Observer design pattern

    Recently read <Head First Design patterns > A Book , This series will quote from the source book , But the content of the article will be more direct , And add some of your own understanding . Observer mode ( Sometimes called a model - View (View) Pattern . Source - Listeners (List ...

  7. C# Quickly delete bin and obj Folder method

    C# Programs always generate bin and obj Folder , In order to reduce the size of the source code , It is necessary to delete these two folders , So I thought of using batch file to delete . The following is the batch code : @echo offset nowPath=%cd%cd /cd ...

  8. LeetCode--176-- The second highest salary

    Problem description : Write a SQL Inquire about , obtain Employee  The second highest salary on the list (Salary) . +----+--------+ | Id | Salary | +----+--------+ | 1 ...

  9. Structure From Motion( Three dimensional reconstruction in two-dimensional moving image )

    SfM(Structure from Motion) brief introduction Structure from motion (SfM) is a photogrammetric range imaging techniqu ...

  10. Binary search tree implementation example (C Language )

    /* search_tree.h */ #ifndef _SEARCH_TREE_H #define _SEARCH_TREE_H struct tree_node; typedef struct t ...