浅析mybatis源码(三)Mapper
2019独角兽企业重金招聘Python工程师标准>>>
这篇主要看下mybatis的Mapper,Mapper可以说是mybatis的入口。这里仅讨论注解的方式。
回顾下第一篇中mybatis是如何使用的。
sqlSession = SqlSessionFactoryUtil.getSqlSession();
productMapper = sqlSession.getMapper(ProductMapper.class);
Product product = productMapper.detail(1);
可以看到获取Session后(第二篇讲到了,本质就是获取到一个数据库连接),获取productMapper,ProductMapper是我们定义的一个接口,detail是我们定义的一个抽象方法。 接口并没有实现方法,因此可以猜想到mybatis帮我们生成了一个实现了ProductMapper接口的类。
思路
那可以试想下,让我们自己实现这个类,是怎样的流程呢?
首先,getMapper有个入参是ProductMapper.class。也就是我们有ProductMapper这个接口,接口上每个方法中的注解上都定义了该如何执行sql。通过反射能够拿到这些sql信息。生成类则可以使用动态代理,因为ProductMapper是接口,我们可以用jdk动态代理。
mybatis生成productMapper流程
mybatis生成productMapper是分两步的,第一步是在初始化的时候addMapper,第二步则是在使用的时候getMapper。为什么要这样做呢,因为解析注解、生成工厂类等都是重复的工作。可以在初始化前计算好。使用的时候拿来用就行了。
getMapper流程
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
getMapper的流程比较简单,就是通过Mapper在knownMappers(addMapper中会讲)中取到对应的Mapper代理工厂。然后通过工厂构建Mapper代理。
addMapper流程
可以看到最终一共生成了三份重要数据,类型分别为Mapper代理工厂类,ResultMap,MappedStatement类。都保存在了Map结构中。
knowMappers保存在了configuration.mapperRegistry中。键是Mapper.class,值是对应的Mapper代理工厂。
resultMaps保存在了configuration中。键是个字符串,这样拼接的”${Mapper包路径}.${Mapper类名}.${执行方法名}.${方法返回类型}“,值是这个方法对应的结果处理配置。
mappedStatments保存在了configuration中。键是个字符串,这样拼接的”${Mapper包路径}.${Mapper类名}.${执行方法名}“,值是这个方法对应的sql执行配置。
那这些数据什么时候使用呢?
在getMapper的时候,便可以取出来Mapper工厂来生成Mapper类。
当执行Mapper中某个方法时,便可以从MappedStatement中找到执行的sql数据,得到结果后,可以从ResultMap中找到定义的结果类型,将结果转为定义的类型。
后面三篇文章会分别从这三个类出发来进行讨论。
转载于//my.oschina.net/u/3361610/blog/3012573
还没有评论,来说两句吧...