前面记录了一片《spring源码学习之整合Mybatis原理分析》之后,这篇记录spring在整合mybatis之后,目标方法的调用过程和事务的管理。
通过这篇文章分析之后,至少需要解决本人关注的两个问题:
- 调用mapper方法的执行过程是怎样的?
- mybatis的事务和spring的事务是如何被管理的?
配置文件还是遵从前面文章的记录,测试用例如下:
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
IAuthUserService authUserServiceImpl = ctx.getBean(AuthUserServiceImpl.class);
AuthUser authUser = new AuthUser();
authUser.setId((long) 4);
int ret = authUserServiceImpl.delete(authUser);
logger.info("执行结果:"+ ret);
}
delete的实现也很简单,用户的软删除,根据主键去更新用户表的is_delete字段的值为0:
@Service
public class AuthUserServiceImpl implements IAuthUserService {
private static Logger logger = Logger.getLogger(AuthUserServiceImpl.class);
@Autowired
private AuthUserMapper authUserMapper;
@Override
public int delete(AuthUser authUser) {
if(authUser == null){
return 0;
}
authUser.setIsDelete((byte) 0);
authUser.setUpdateTime(new Date());
return authUserMapper.updateByPrimaryKeySelective(authUser);
}
}
目标方法执行过程
这篇文章中《spring源码学习之整合Mybatis原理分析》记录了,authUserMapper变量指向的实例,实际上是一个代理类,程序在调用authUserMapper对象的某个方法的时候,就会调用到MapperProxy对象的invoke()方法。接下来就分析这个MapperProxy的invoke()方法。
先贴一张时序图,以后有时间了,在来详细记录,感觉mybatis里面的东西写得挺乱的。
大概的过程分为下面几步:
- 创建一个DefaultSqlSession,并将这个DefaultSqlSession和DefaultSqlSessionFactory做一个绑定,记录在spring-tx的TransactionSynchronizatioManager事物管理器中。
- 创建一个SqlSessionUtils.SqlSessionSynchronization对象,将这个对象注册到TransactionSynchronizatioManager事物管理器中,这个对象在事物提交阶段会用到。
- 获取一个connection,这个连接是从SpringManagedTransaction中获取的,但是实际上也是根据dataSource间接从spring中的TransactionSynchronizatioManager事物管理器中获取的,事物管理器中的这个connection是在spring创建事物的时候创建的,并且connection和dataSource做了一个ThreadLocal绑定。
- 执行prepareStatement,创建JDBC42PreparedStatement,这个类是mysql-connector包中的对象,不再属于mybatis包。
- 设置参数,替换sql中的占位符“?”。
- 调用JDBC42PreparedStatement的excute方法,执行sql脚本。
- 处理返回结果。
浓缩之后,就是上面这些步骤,创建了太多的类,有些类有些泛滥了,没感觉有多大的作用。
事物提交
从上面的时序图可以看得出来,mybatis并没有创建自己的事物管理器,创建了一个SpringManagedTransaction管理器,是在mybatis-spring包中的,而这个事物管理器也是委托spring在管理事物。具体来讲,执行目标方法的过程中,需要创建一个connection连接,这个连接是通过SpringManagedTransaction事物管理器,最终从spring的TransactionSynchronizatioManager事物管理器中获取的。
再看看执行完目标方法之后,及数据库的操作之后,事物的提交或者回滚在哪儿完成的。上时序图:
执行完目标方法之后,程序返回到TransactionInterceptor,这个拦截器定义了事物的框架,
- 首先开启创建事物。
- 执行目标方法,进行数据库操作。
- 提交事物或者回滚。
- 清理缓存或者临时变量。
- 释放连接connection,连接返回到连接池。
spring事务管理器对外提供了回调接口,这个回调接口允许外部程序可以在事物提交之前和提交之后,做一些事情。mybatis的SqlSessionUtils.SqlSessionSynchronization就实现了这些接口。SqlSessionSynchronization这个是什么时候注册到spring的事物管理器里的呢?答案就是上面的时序图中。
先记录这些吧,等以后有充足时间了,在详细分析,这儿先描述轮廓。再贴一张类图: