1、事务未提交,异步获取不到数据
package com.spring.pro.service.impl;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.spring.pro.entity.User;
import com.spring.pro.mapper.UserMapper;
import com.spring.pro.service.UserService;
import lombok.extern.slf4j.Slf4j;
/**
* @Title: UserServiceImpl.java
* @ProjectName com.spring.pro.threadpool
* @Description:
* @author ybwei
* @date 2020年1月10日 下午4:37:35
*/
@Component("userService")
@Slf4j
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource(name = "taskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override
@Transactional
public void testTransactional() {
User user = new User();
user.setName("张三");
user.setAge(12);
userMapper.insertSelective(user);
// 异步
CompletableFuture.runAsync(() -> {
handleDb(user.getId());
}, threadPoolTaskExecutor);
try {
TimeUnit.SECONDS.sleep(1);// 休眠1秒,测试使用,保证异步执行时,事务未提交
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("添加后user:{}", JSON.toJSONString(user));
}
private void handleDb(Long id) {
User user = userMapper.selectByPrimaryKey(id);
log.info("异步user:{}", JSON.toJSONString(user));
}
}
打印日志如下
[INFO ] 2020-01-10 16:52:34.907 [taskExecutor-1] c.s.pro.service.impl.UserServiceImpl - 异步user:null
[INFO ] 2020-01-10 16:52:35.659 [http-nio-8080-exec-5] c.s.pro.service.impl.UserServiceImpl - 添加后user:{"age":12,"id":47025,"name":"张三"}
因为事务还未提交,所以异步中获取user是空的。
2、事务已提交,获取数据库数据
异步中的user,我们想要的是事务提交后的数据
package com.spring.pro.service.impl;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.spring.pro.entity.User;
import com.spring.pro.mapper.UserMapper;
import com.spring.pro.service.UserService;
import lombok.extern.slf4j.Slf4j;
/**
* @Title: UserServiceImpl.java
* @ProjectName com.spring.pro.threadpool
* @Description:
* @author ybwei
* @date 2020年1月10日 下午4:37:35
*/
@Component("userService")
@Slf4j
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource(name = "taskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override
@Transactional
public void testTransactional() {
User user = new User();
user.setName("张三");
user.setAge(12);
userMapper.insertSelective(user);
// 异步
CompletableFuture.runAsync(() -> {
handleDb(user.getId());
}, threadPoolTaskExecutor);
log.info("添加后user:{}", JSON.toJSONString(user));
}
private void handleDb(Long id) {
try {
TimeUnit.SECONDS.sleep(1);// 休眠1秒,测试使用,保证异步执行时,事务已提交
} catch (InterruptedException e) {
e.printStackTrace();
}
User user = userMapper.selectByPrimaryKey(id);
log.info("异步user:{}", JSON.toJSONString(user));
}
}
打印日志如下:
[INFO ] 2020-01-10 16:57:14.862 [http-nio-8080-exec-7] c.s.pro.service.impl.UserServiceImpl - 添加后user:{"age":12,"id":47027,"name":"张三"}
[INFO ] 2020-01-10 16:57:15.866 [taskExecutor-2] c.s.pro.service.impl.UserServiceImpl - 异步user:{"age":12,"createTime":1578646634000,"id":47027,"name":"张三","points":0,"status":0,"updateTime":1578646634000}
3、解决问题
第二步,休眠1秒,并不是解决问题的方案。
package com.spring.pro.service.impl;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Resource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import com.alibaba.fastjson.JSON;
import com.spring.pro.entity.User;
import com.spring.pro.mapper.UserMapper;
import com.spring.pro.service.UserService;
import lombok.extern.slf4j.Slf4j;
/**
* @Title: UserServiceImpl.java
* @ProjectName com.spring.pro.threadpool
* @Description:
* @author ybwei
* @date 2020年1月10日 下午4:37:35
*/
@Component("userService")
@Slf4j
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource(name = "taskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override
@Transactional
public void testTransactional() {
User user = new User();
user.setName("张三");
user.setAge(12);
userMapper.insertSelective(user);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// 异步
CompletableFuture.runAsync(() -> {
handleDb(user.getId());
}, threadPoolTaskExecutor);
}
});
log.info("添加后user:{}", JSON.toJSONString(user));
}
private void handleDb(Long id) {
User user = userMapper.selectByPrimaryKey(id);
log.info("异步user:{}", JSON.toJSONString(user));
}
}
TransactionSynchronizationManager.registerSynchronization可以保证事务提交后,才会执行afterCommit里面的异步方法。