文档章节

mybatis中session.getMapper方法源码分析

writeademo
 writeademo
发布于 07/20 16:34
字数 549
阅读 77
收藏 0

 

0开始代码AuthorMapper mapper = session.getMapper(AuthorMapper.class);

1 DefaultSqlSession类

 

@Override

public <T> T getMapper(Class<T> type) {

//最后会去调用MapperRegistry.getMapper

return configuration.<T>getMapper(type, this);

}

 

2 Configuration类

 

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {

return mapperRegistry.getMapper(type, sqlSession);

}

3 MapperRegistry类

 

//返回代理类

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);

}

}

MapperProxyFactory<T> 类

public T newInstance(SqlSession sqlSession) {

final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);

return newInstance(mapperProxy);

}

 

protected T newInstance(MapperProxy<T> mapperProxy) {

//用JDK自带的动态代理生成映射器

return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

}

 

MapperProxy类

public class MapperProxy<T> implements InvocationHandler, Serializable{

 

public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {

this.sqlSession = sqlSession;

this.mapperInterface = mapperInterface;

this.methodCache = methodCache;

}

}

 

 

 

//去缓存中找MapperMethod

private MapperMethod cachedMapperMethod(Method method) {

MapperMethod mapperMethod = methodCache.get(method);

if (mapperMethod == null) {

//找不到才去new

mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());

methodCache.put(method, mapperMethod);

}

return mapperMethod;

}

 

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//代理以后,所有Mapper的方法调用时,都会调用这个invoke方法

//并不是任何一个方法都需要执行调用代理对象进行执行,如果这个方法是Object中通用的方法(toString、hashCode等)无需执行

if (Object.class.equals(method.getDeclaringClass())) {

try {

return method.invoke(this, args);

} catch (Throwable t) {

throw ExceptionUtil.unwrapThrowable(t);

}

}

//这里优化了,去缓存中找MapperMethod

final MapperMethod mapperMethod = cachedMapperMethod(method);

//执行

return mapperMethod.execute(sqlSession, args);

}

MapperMethod类

 

 

//执行

public Object execute(SqlSession sqlSession, Object[] args) {

Object result;

//可以看到执行时就是4种情况,insert|update|delete|select,分别调用SqlSession的4大类方法

if (SqlCommandType.INSERT == command.getType()) {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.insert(command.getName(), param));

} else if (SqlCommandType.UPDATE == command.getType()) {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.update(command.getName(), param));

} else if (SqlCommandType.DELETE == command.getType()) {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.delete(command.getName(), param));

} else if (SqlCommandType.SELECT == command.getType()) {

if (method.returnsVoid() && method.hasResultHandler()) {

//如果有结果处理器

executeWithResultHandler(sqlSession, args);

result = null;

} else if (method.returnsMany()) {

//如果结果有多条记录

result = executeForMany(sqlSession, args);

} else if (method.returnsMap()) {

//如果结果是map

result = executeForMap(sqlSession, args);

} else {

//否则就是一条记录

Object param = method.convertArgsToSqlCommandParam(args);

result = sqlSession.selectOne(command.getName(), param);

}

} else {

throw new BindingException("Unknown execution method for: " + command.getName());

}

if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {

throw new BindingException("Mapper method '" + command.getName()

+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");

}

return result;

}

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
writeademo
粉丝 25
博文 555
码字总数 205067
作品 0
东城
私信 提问
Mybatis源码概览(二) ---Plugin扩展与Spring结合原理

本文主要介绍Mybatis通过动态代理避免对sqlSession直接调用,而是通过MapperProxy代理技术生成了具体dao接口的Mapper实例,里面封装了对sqlSession的调用;Mybatis预留了Interceptor接口,用...

robin-yao
2016/03/23
530
0
基于MyBatis3.0.6的基本操作介绍

每 一 个 MyBatis 的 应 用 程 序 都 以 一 个 SqlSessionFactory 对 象 的 实 例 为 核 心 。SqlSessionFactory本身是由SqlSessionFactoryBuilder创建的,一般而言,在一个应用中,一个数据...

JAVA_NINA
2015/04/21
0
0
基于MyBatis3.0.6的基本操作介绍

每 一 个 MyBatis 的 应 用 程 序 都 以 一 个 SqlSessionFactory 对 象 的 实 例 为 核 心 。SqlSessionFactory本身是由SqlSessionFactoryBuilder创建的,一般而言,在一个应用中,一个数据...

玄空
2012/09/25
0
0
MyBatis学习之简单增删改查操作、MyBatis存储过程、MyBatis分页、MyBatis一对一、MyBatis一对多

一、用到的实体类如下: Student.java [html] view plaincopy package com.company.entity; import java.io.Serializable; import java.util.Date; public class Student implements Seriali......

thinkyoung
2014/12/14
0
0
【深入浅出MyBatis系列一】MyBatis入门

深入浅出MyBatis系列 【深入浅出MyBatis系列一】MyBatis入门 【深入浅出MyBatis系列二】配置简介(MyBatis源码篇) 【深入浅出MyBatis系列三】Mapper映射文件配置 【深入浅出MyBatis系列四】...

陶邦仁
2015/12/22
4.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

PHP生成CSV之内部换行

当我们使用PHP将采集到的文件内容保存到csv文件时,往往需要将采集内容进行二次过滤处理才能得到需要的内容。比如网页中的换行符,空格符等等。 对于空格等处理起来都比较简单,这里我们单独...

豆花饭烧土豆
今天
2
0
使用 mjml 生成 thymeleaf 邮件框架模板

发邮件算是系统开发的一个基本需求了,不过搞邮件模板实在是件恶心事,估计搞过的同仁都有体会。 得支持多种客户端 支持响应式 疼彻心扉的 outlook 多数客户端只支持 inline 形式的 css 布局...

郁也风
今天
8
0
让哲学照亮我们的人生——读《医务工作者需要学点哲学》有感2600字

让哲学照亮我们的人生——读《医务工作者需要学点哲学》有感2600字: 作者:孙冬梅;以前读韩国前总统朴槿惠的著作《绝望锻炼了我》时,里面有一句话令我印象深刻,她说“在我最困难的时期,...

原创小博客
今天
4
0
JAVA-四元数类

public class Quaternion { private final double x0, x1, x2, x3; // 四元数构造函数 public Quaternion(double x0, double x1, double x2, double x3) { this.x0 = ......

Pulsar-V
今天
18
0
Xshell利用Xftp传输文件,使用pure-ftpd搭建ftp服务

Xftp传输文件 如果已经通过Xshell登录到服务器,此时可以使用快捷键ctrl+alt+f 打开Xftp并展示Xshell当前的目录,之后直接拖拽传输文件即可。 pure-ftpd搭建ftp服务 pure-ftpd要比vsftp简单,...

野雪球
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部