当前位置: 首页 > news >正文

Mybatis中sqlSession.getMapper背后的原理

在通过MyBatis操作数据库之前我们一定先通过Session对象获取指定Mappper接口的代理对象。如下代码所示:

public class UserMapper{@Select(value="SELECT * FROM user")public List<User> findAll();
}

public static void main(String [] args){Configuration configuration = new Configuration();configuration.addMapper(UserMapper.class);SqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory(configuration);// 获取SqlSession对象try(SqlSession sqlSession = sqlSessionFactory.openSession();){UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List<User> userList = userMapper.findAll();}catch(Exception e){//TODO 异常信息}
}

调用链

1.DefaultSqlSession.调用getMapper方法 -> 2.Configuration.调用getMapper方法 -> 3.MapperRegistry调用getMapper方法|||-------------------------------------------------------------------------------------||||-->4.判断knownMappers缓存是否已经解析过指定的Mapper接口,没解析过抛错(在调用addMapper方法时就将接口添加到缓存中并对接口中的方法进行解析).解析过创建代理对象public <T> T getMapper(Class<T> type, SqlSession sqlSession) {final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);if (Objects.isNull(mapperProxyFactory)){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);}}|||-->  5.创建代理对象,MapperProxy实现了InvocationHandler接口,使用JDK动态代理创建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);}

注意第5代逻辑:

   // 已解析过的Mapper接口及对应的代理工厂缓存private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();public <T> T getMapper(Class<T> type, SqlSession sqlSession) {final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);if (Objects.isNull(mapperProxyFactory)) {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);}}

先从缓存中获取接口对应的代理工厂,并判断是否存储代理工厂。不存在时抛错,表示此接口没有注册过无法创建代理对象.
何时向缓存中添加接口及对应的代理工厂呢?如下代码:

  public <T> void addMapper(Class<T> type) {// mapper必须是接口!才会添加if (type.isInterface()) {if ( knownMappers.containsKey((type)) {// 如果重复添加了,报错throw new BindingException("Type " + type + " is already known to the MapperRegistry.");}boolean loadCompleted = false;try {// 将mapper接口放入缓存并为其创建独立的mapper接口代理对象工厂// 每个Mapper接口有一个独立的代理工厂knownMappers.put(type, new MapperProxyFactory<T>(type));// 在运行分析器之前添加类型非常重要// 否则,绑定可能会由// 映射器解析器。如果类型已知,则不会尝试。MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);// 解析mapper接口及相应的mapper.xml文件parser.parse();loadCompleted = true;} finally {// 如果加载过程中出现异常需要再将这个mapper从mybatis中删除,这种方式比较丑陋吧,难道是不得已而为之?if (!loadCompleted) {knownMappers.remove(type);}}}
}

在注册Mapper 接口时,会向缓存中添加接口对应的代理工厂,以便后面通过接口获取代理对象调用方法。

http://www.lryc.cn/news/334014.html

相关文章:

  • [环境配置]conda 64位安装32位python
  • 某虚假交友APP(信息窃取)逆向分析
  • 基于FPGA的按键消抖
  • 1.网络编程-网络协议
  • 代码+视频,手动绘制logistic回归预测模型校准曲线(Calibration curve)(2)
  • 金融数据_Scikit-Learn决策树(DecisionTreeClassifier)实例
  • bash的login shell与non-login shell,以及各自的初始化过程
  • 为什么苹果 Mac 电脑需要使用清理软件?
  • 33. UE5 RPG使用增强输入激活GameplayAbility(三)
  • speech to text 库FastASR交叉编译arm target的配置
  • WPS快速将插入Excle数据插入Word
  • Springboot 集成Rabbitmq之延时队列
  • 【云开发笔记NO.22】运用云原生产品打造技术中台
  • C++进阶(五) 哈希
  • 【算法基础】基于异或的排序、基于异或的经典面试题
  • HTML2:列表和表格
  • 用于无人机小型化设计的高精度温补晶振
  • 轨迹规划 | 图解最优控制LQR算法(附ROS C++/Python/Matlab仿真)
  • 工业视觉检测
  • wheeltec轮趣ROS教育机器人的网络连接
  • 【Linux ARM 裸机】开发环境搭建
  • 怎么保证缓存与数据库的最终一致性?
  • 免费SSL通配符证书/SSL泛域名证书获取教程
  • mysql结构与sql执行流程
  • vue快速入门(十二)v-key索引标志
  • 智能网联汽车自动驾驶数据记录系统DSSAD数据配置
  • linux知识点
  • 微信小程序实现滚动标签
  • 大语言模型上下文窗口初探(下)
  • Java整合ElasticSearch8.13