生于憂患忍些,死于安樂(lè)
在UsersServiceImpl中有兩個(gè)事務(wù)方法
- InsertUsers() 和InsertCuser() 都是被事務(wù)注解所申明的方法守呜;且InsertUsers中調(diào)用了InsertCuser
- InsertUsers使用REQUIRED行為傳播
- InsertCusers使用REQUIRES_NEW行為傳播
package com.springboot.study.demo1.service.impl;
import com.springboot.study.demo1.entity.Cuser;
import com.springboot.study.demo1.entity.Users;
import com.springboot.study.demo1.service.CuserService;
import com.springboot.study.demo1.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.List;
import java.util.Map;
/**
* @program: springboot_study
* @description:
* @author: yinkai
* @create: 2020-03-02 15:31
*/
@Service
public class UsersServiceImpl implements UsersService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private UsersService usersService;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void InsertUsers() {
jdbcTemplate.update("INSERT INTO users(id,name, age, email) VALUES (?, ?, ?, ?);", 111, "InsertUsers", 24, "InsertUsers@qq.com");
//打印事務(wù)id
List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID( );");
System.out.println(maps + TransactionSynchronizationManager.getCurrentTransactionName());
//調(diào)用本service中另一個(gè)方法
usersService.InsertCuser();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void InsertCuser() {
jdbcTemplate.update("INSERT INTO users(id,name, age, email) VALUES (?, ?, ?, ?);", 112, "InsertUsers", 24, "InsertUsers@qq.com");
//打印事務(wù)id
List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID( );");
System.out.println(maps + TransactionSynchronizationManager.getCurrentTransactionName());
}
}
我們來(lái)看看執(zhí)行日志,可以看到兩者打印的事務(wù)id相同。使用的是同一個(gè)事務(wù)。這違背了REQUIRES_NEW傳播行為的語(yǔ)義了!
理論上此時(shí)兩個(gè)方法分別會(huì)開(kāi)啟自己的事務(wù)才對(duì)呀羞芍?為什么InsertCuser方法沒(méi)有開(kāi)啟事務(wù)?
如果理解了spring實(shí)現(xiàn)申明式事務(wù)的原理就都明白了恶迈。我們都知道spring底層是使用動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)事務(wù)切面的涩金。所以就必須走代理對(duì)象調(diào)用方法才能使方法增強(qiáng)生效!
注意看代碼中是如何調(diào)用InsertCuser方法的:InsertCuser(cuser);
這就相當(dāng)于同過(guò)this調(diào)用本類(lèi)方法 this.InsertCuser(cuser);
此處的this指向目標(biāo)對(duì)象而不是代理對(duì)象谱醇,因此調(diào)用this.InsertCuser()將不會(huì)執(zhí)行InsertCuser事務(wù)切面,即不會(huì)執(zhí)行事務(wù)增強(qiáng)步做,因此b方法的事務(wù)定義@Transactional(propagation = Propagation.REQUIRES_NEW)
將不會(huì)實(shí)施副渴,即結(jié)果是InsertCuser和InsertUsers方法的事務(wù)定義是一樣的。
所以只要得到usersService的代理對(duì)象就行了~
可以使用自我注入
的方式解決這個(gè)問(wèn)題
代碼修改如下
在UsersService 類(lèi)中再注入一個(gè)UsersService 實(shí)例全度,然后通過(guò)這個(gè)實(shí)例屬性進(jìn)行InsertCuser方法的調(diào)用煮剧。豈不美哉?
package com.springboot.study.demo1.service.impl;
import com.springboot.study.demo1.entity.Cuser;
import com.springboot.study.demo1.entity.Users;
import com.springboot.study.demo1.service.CuserService;
import com.springboot.study.demo1.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.List;
import java.util.Map;
/**
* @program: springboot_study
* @description:
* @author: yinkai
* @create: 2020-03-02 15:31
*/
@Service
public class UsersServiceImpl implements UsersService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private UsersService usersService;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void InsertUsers() {
jdbcTemplate.update("INSERT INTO users(id,name, age, email) VALUES (?, ?, ?, ?);", 111, "InsertUsers", 24, "InsertUsers@qq.com");
//打印事務(wù)id
List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID( );");
System.out.println(maps + TransactionSynchronizationManager.getCurrentTransactionName());
//調(diào)用本service中另一個(gè)方法
usersService.InsertCuser();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void InsertCuser() {
jdbcTemplate.update("INSERT INTO users(id,name, age, email) VALUES (?, ?, ?, ?);", 112, "InsertUsers", 24, "InsertUsers@qq.com");
//打印事務(wù)id
List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID( );");
System.out.println(maps + TransactionSynchronizationManager.getCurrentTransactionName());
}
}
執(zhí)行如下将鸵,已經(jīng)不是同一個(gè)事務(wù)了
還可以使用這種較為優(yōu)雅的方式
((UsersService) AopContext.currentProxy())