Using Spring's transaction management @Transactional

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/cblstc/article/details/94582905

Foreword

Recently when refactoring code and found a serious bug: error after the transaction method, does not even roll back, because I have to catch the exception, the following specific reasons speak. Fear very fine thinking, the whole project is the kind of writing. So, to begin research and testing @Transactional comment.
@Transactional can help us to automatically manage transactions. Usually in the process of service plus the annotation layer. But there are a lot of pit! The following codes are shapeless code, commonly known as pseudo-code.

A pit: valid only for external calls

Internal call transaction method causes the transaction invalid because of spring dynamic proxies for transaction management, external calls can only intercept, unable to manage internal calls.

class UserController {
    // 外部调用,受事务管理
    userService.saveUser();
}
class UserService {
    @Transation
    public void saveUser() {}
    
    public void saveUserInternal() {
        // 内部调用,不受事务管理
        saveUser();
    }
}

The solution: get a proxy object, and the object through a proxy to call
the first step, open exposure to Agent

<aop:aspectj-autoproxy expose-proxy="true" />

The second step, through a proxy object to call the transaction method

((UserService)AopContext.getProxy()).saveUser();

Pit II: valid only for public methods

Because the transaction annotation only effective external call (refer to pit a), private method can only be called internally, so private invalid well understood. But why protected invalid. stackoverflow of this answer to explain my confusion.
Here Insert Picture Description
This means that: JDK agent does not support interception of protected methods, but CGLIB is possible, but not recommended, then Spring in order to unify those guys, cut directly support protected method.

Hang three: Unchecked exceptions only effective

What is abnormal subjects and Unchecked exceptions? Simply put, the subject is abnormal or if you do not catch the exception thrown, then the compiler will complain, common, such as FileInputStream, you either catch the exception, or throw an exception.
Here Insert Picture Description
Solution: @Transactional (rollbackFor = Exception.class)

@Transactional(rollbackFor = Exception.class)
public void saveFile() throws FileNotFoundException {
	// 数据操作
	userDao.saveUser();
    // 会抛出异常,因为设置了rollbackFor属性,会回滚
	InputStream in = new FileInputStream(new File("xxx.xxx");
}

Hang four: only valid for an exception thrown

Exception caught, the equivalent of hidden anomalies, abnormal does not automatically rollback. If you must capture, capture manually rolled back inside the code block

@Transactional
public void saveUser() {
    try {
        saveUser();   
    } catch(Exception e) { 
		// 手动关闭事务
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

Outstanding

I encounter when debugging a problem, the transaction method, the first after deleting the query is normal; but after saving the first check, you can not find the saved data. You big brother, if you know what the reason may demand lower.

data

  1. @Transactional transaction propagation behavior

  2. Why @Transactional not be used on protected method?

Guess you like

Origin blog.csdn.net/cblstc/article/details/94582905