我们接着上一篇Mybatis(3),我们来看看上面获取Mapper的过程:
我们从mybatis主要构件的执行流程:
接下来我们来看看SqlSession是什么获取Mapper的:
AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
接着看看getMapper:
public <T> T getMapper(Class<T> type) {
//configuration上下文中根据Class类型来查找
return configuration.<T>getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//从mapperRegistry中获取mapper代理
return mapperRegistry.getMapper(type, sqlSession);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//获取生产mapper代理的的MapperProxyFactory
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//真正创建代理mapper的的地方
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
//创建mapper代理
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
//创建mapper代理
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
这里我们就可以很明白的看出,Mybatis中为什么只有Mapper接口便能够运行SQL?
答:因为映射器的XML文件的命名空间对应的就是Mapper接口的全路劲,那么根据全路径和方法名便能够绑定起来,通过代理技术,为接口提供代理类,使接口跑起来,而后采用命令模式,最后是使用SqlSession接口的方法使的它能够执行查询。
这里我们可以理解SQL Mapper:是由一个Java接口和XML文件(注解)构成的
最后我们来看看Mapper映射器内部组成:
1、MappedStatement:保存映射器的一个节点。包括许多我们配置的SQL,Sql的id、缓存信息、resultMap、parameterType、resultType、languageDriver
2、SqlSource:它提供BoundSql对象的地方,它是MappedStatement的一个属性。主要作用根据参数和其他规则组装SQL
3、 BoundSql:它是建立SQL和参数的地方。它有3个常用的属性:SQL、parameterObject、parameterMappings
BoundSql:
目的:在插件中往往需要拿到BoundSql:获取运行的SQL和参数以及参数规则,做出适当的修改,来满足我们的特殊需要
BoundSql的3个属性:parameterMappings、parameterObject和sql
• parameterObject:参数本身
• sql:就是我们书写在映射器里面的一条SQL,在插件的情况下,我们可以根据需要进行改写。
• parameterMappings:它是一个List<ParameterMapping>,ParameterMapping的对象描述的是参数。包括:参数的属性、名称、表达式、javaType、jdbcType、typeHandler等重要信息。通过它可以实现参数和SQL的结合,以便PreparedStatement能够通过它找到parameterObject对象的属性并设置参数,使程序准确的执行。