Mybatis获取代理对象
- mybatis-config.xml里
标签可以放置多个environment,这里可以切换test和develop数据源 - databaseIdProvider提供多种数据库,在xml映射文件里选择databaseId即可使用对应的数据库
- Oracle的自增是使用Sequence实现的,若要获取插入数据的主键,在xml映射里写上selectKey标签,select seq.nextval from dual;
- 哪些地方不能使用占位符?比如分表时表名,orderby,desc
- @Mapkey("id")指定返回类型为map时,将id作为key
1. mybatis参数绑定的过程
我们写一个UserMapper接口,Mybatis会为改接口创建一个MapperProxy对象。
1.1 MapperRegistry
在继续之前,先来了解一下MapperRegistry。
- MapperRegistry是mapper的注册类,提供了注册一个包下面的所有Mapper接口。内部维护了一个
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
map以mapper接口类为key,value是接口类对应的代理工厂。
void addMapper(Class<T> type)
方法简单的将type放进knownMappers里面。不过,这里面还有
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
这样一个解析操作,暂不做分析。
2. <T> T getMapper(Class<T> type, SqlSession sqlSession)
该方法是本类最重要的一个方法了,获取Mapper接口的代理对象也正是从该方法获取的。
该方法实现就是,knownMappers.get(type)得到代理对象工厂mapperProxyFactory,返回的是mapperProxyFactory.newInstance(sqlSession)
。
进入该方法发现过程也比较简单,构造了一个MapperProxy对象
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
再进去看
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
发现这就是标准的JDK面向接口的动态代理啊。要问对应的InvocationHandler在哪里?mapperProxy就是啦。
至此,Mybatis如何获取Mapper接口的代理对象已经解决。
再梳理一下整个流程:
sqlsession.getMapper->configuration.getMapper->mapperRegistry.getMapper->获取Mapper代理对象
1.2
创建好MapperProxy对象之后,调用Mapper.xx方法时就会走MapperProxy的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {//如果方法是在Object里面的,放行
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);//缓存method方法
return mapperMethod.execute(sqlSession, args); // 执行
}
发现关键点在于mapperMethod.execute(sqlSession, args)
方法
当你准备好了,机会来临的时候,你才能抓住
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现