文档章节

mybatis中session.getMapper方法源码分析

writeademo
 writeademo
发布于 07/20 16:34
字数 549
阅读 50
收藏 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
粉丝 24
博文 534
码字总数 191198
作品 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

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 小心着凉 @红薯

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:5.33起,其声呜呜然,如怨如慕,如泣如诉。余音袅袅,不绝如缕。分享Arch Enemy的单曲《Bridge Of Destiny (2009)》 《Bridge Of...

小小编辑
今天
211
4
what f,,

anlve
今天
9
0
初级开发-编程题

` public static void main(String[] args) { System.out.println(changeStrToUpperCase("user_name_abc")); System.out.println(changeStrToLowerCase(changeStrToUpperCase("user_name_abc......

小池仔
今天
15
0
现场看路演了!

HiBlock
昨天
23
0
Rabbit MQ基本概念介绍

RabbitMQ介绍 • RabbitMQ是一个消息中间件,是一个很好用的消息队列框架。 • ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的s...

寰宇01
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部