Mybatis3源码分析(一):从sqlSession说起

springboot引入mybatis框架 springboot引入mybatis框架 1.前言 springboot整合mybatis框架使用已经逐渐成为一种主流的开发架构,mybatis是一个基于jdbc优化的框架,它的主要特点之一就是动态sql,它将sql语句写到xml文件中,通过配置文件来执行,减少了sql语句的拼接,并且不用修改原来的java代码,大大减低了耦合度。而springboot是一个轻量级框架,它对代码的侵入性远远小于同类框架,并且springboot还有能够集成其他框架的特性,所以他两经常在一起使用。 2.配置文件 话不多说,先 阅读详情
  


分析MyBatis3的源码首先得从sqlSessionFactory开始,先来看一段spring配置文件中Mybaits的sqlSessionFactory的配置。

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  destroy-method="close">  
   <property name="driverClassName" value="${jdbc.driver}" />  
   <property name="url" value="${jdbc.url}" />  
   <property name="username" value="${jdbc.username}" />  
   <property name="password" value="${jdbc.password}" />  
</bean>  
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
   <property name="dataSource" ref="dataSource" />
   <property name="configLocation" value="classpath:configuration.xml"></property> 
   <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml"/>  
   <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
</bean>
<bean id="blogMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
       <property name="mapperInterface"  
           value="com.tiantian.mybatis.mapper.BlogMapper" />  
      <property name="sqlSessionFactory" ref="sqlSessionFactory" />  
</bean>   

    spring会调用sqlSessionFactory的无参构造函数创建实例,并将dataSource和映射文件路径注入进去初始化sqlSessionFactory。这里的SqlSessionFactoryBean的实现依赖于mybatis社区自行开发的支持包,我们来看看它是怎么读取xml配置文件创建sessionFactory的:

protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
    //代表配置的对象
    Configuration configuration;
    //xml配置创建者
    XMLConfigBuilder xmlConfigBuilder = null;
    //spring中注入的配置文件路径,如果不存在使用默认配置
    if (this.configLocation != null) {
      xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
      configuration = xmlConfigBuilder.getConfiguration();
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
      }
      configuration = new Configuration();
      configuration.setVariables(this.configurationProperties);
    }
    //如果配置了objectFactory使用此配置类
    if (this.objectFactory != null) {
      configuration.setObjectFactory(this.objectFactory);
    }
    //同上
    if (this.objectWrapperFactory != null) {
      configuration.setObjectWrapperFactory(this.objectWrapperFactory);
    }
    //如果配置了typeAliases(实体类别名标签)的基包则不用在configuration文件中配置
    if (hasLength(this.typeAliasesPackage)) {
      String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
          ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
      for (String packageToScan : typeAliasPackageArray) {
        configuration.getTypeAliasRegistry().registerAliases(packageToScan,
                typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
        if (logger.isDebugEnabled()) {
          logger.debug("Scanned package: '" + packageToScan + "' for aliases");
        }
      }
    }
    //如果是直接配置的实体类别名则在配置对象中注册
    if (!isEmpty(this.typeAliases)) {
      for (Class<?> typeAlias : this.typeAliases) {
        configuration.getTypeAliasRegistry().registerAlias(typeAlias);
        if (logger.isDebugEnabled()) {
          logger.debug("Registered type alias: '" + typeAlias + "'");
        }
      }
    }
    //是否配置mybaits的一些插件
    if (!isEmpty(this.plugins)) {
      for (Interceptor plugin : this.plugins) {
        configuration.addInterceptor(plugin);
        if (logger.isDebugEnabled()) {
          logger.debug("Registered plugin: '" + plugin + "'");
        }
      }
    }
    //是否配置typeHandler的基包
    if (hasLength(this.typeHandlersPackage)) {
      String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,
          ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
      for (String packageToScan : typeHandlersPackageArray) {
        configuration.getTypeHandlerRegistry().register(packageToScan);
        if (logger.isDebugEnabled()) {
          logger.debug("Scanned package: '" + packageToScan + "' for type handlers");
        }
      }
    }
    //是否直接配置了typeHandler
    if (!isEmpty(this.typeHandlers)) {
      for (TypeHandler<?> typeHandler : this.typeHandlers) {
        configuration.getTypeHandlerRegistry().register(typeHandler);
        if (logger.isDebugEnabled()) {
          logger.debug("Registered type handler: '" + typeHandler + "'");
        }
      }
    }
    //如果xmlConfigBuilder存在则开始分析创建Configuration对象
    if (xmlConfigBuilder != null) {
      try {
        xmlConfigBuilder.parse();

        if (logger.isDebugEnabled()) {
          logger.debug("Parsed configuration file: '" + this.configLocation + "'");
        }
      } catch (Exception ex) {
        throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
      } finally {
        ErrorContext.instance().reset();
      }
    }
    //事务工厂是否配置
    if (this.transactionFactory == null) {
      this.transactionFactory = new SpringManagedTransactionFactory();
    }
    //设置Configuration的环境对象
    Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
    configuration.setEnvironment(environment);
 
    if (this.databaseIdProvider != null) {
      try {
        configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
      } catch (SQLException e) {
        throw new NestedIOException("Failed getting a databaseId", e);
      }
    }
    //是否配置mapperLocations,如果存在解析创建这些mapper,mapper是mybaits管理各种sql的容器
    if (!isEmpty(this.mapperLocations)) {
      for (Resource mapperLocation : this.mapperLocations) {
        if (mapperLocation == null) {
          continue;
        }

        try {
          XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
              configuration, mapperLocation.toString(), configuration.getSqlFragments());
          xmlMapperBuilder.parse();
        } catch (Exception e) {
          throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
        } finally {
          ErrorContext.instance().reset();
        }

        if (logger.isDebugEnabled()) {
          logger.debug("Parsed mapper file: '" + mapperLocation + "'");
        }
      }
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("Property 'mapperLocations' was not specified or no matching resources found");
      }
    }
    //创建sqlSessionFactoryBean
    return this.sqlSessionFactoryBuilder.build(configuration);
  }

    从mybatis创建sqlSessionFactoryBean的过程可以看出,mybaits默认使用spring的事务管理功能或者由第三方实现,它自身并没有提供事务管理能力。其次,它拥有跟其它框架差不多的解析xml过程,都是将xml解析成一个Configuration对象随时取用。到这里我们就得到了一个sqlSessionFactoryBean对象(实际是mybatis本身的DefaultSqlSessionFactory对象),我们可以在DAO中注入这个对象并利用openSession的方法获取SqlSession对象从而进行各种数据库操作。

Spring整合MyBatis之SqlSessionFactory对象的产生 目录为什么 `MyBatis` 要和 `Spring` 整合`Spring` 整合 `MyBatis``Maven` 依赖创建 `Spring` 配置文件 为什么 MyBatis 要和 Spring 整合 Spring 会帮助我们管理 bean:省去我们对 SqlSessionFactory、SqlSession、Mapper 这些核心对象(bean)的创建,不需要我们手工去创建了,Spring 会通过 IOC 容器来帮我们管理这些对象 Spring 使用 xxxTemplate 封装了方法:Spring 阅读详情

相关推荐

Mybatis源码分析之SqlSessionFactory,SqlSession和连接池

简单介绍下mybatis获取SqlSession和进行sql操作的例子 InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); S

hcy54213的博客 9477

ssm整合(重)

更加简洁的办法

weixin_43189971的博客 693

同一个方法中,Mybatis多次请求数据库,是否要创建多个SqlSession会话?

可能最近撸多了,当时脑子里一片模糊,眼神迷离,突然想到一个问题:我们每次执行SQL都会创建一个SqlSession,那么在事务中由多个mapper执行多条sql,每个sql都会创建sqlSession吗?

qq_16159433的博客 6807

spring与mybatis的整合

关于spring与mybatis的整合,总所周知,spring是管理组件的创建,使用和删除的,那么当spring与mybatis进行整合时,则需要将mybatis的核心对象交给spring进行管理,包括SqlsessionFactory、Sqlsession等。 这样做的好处是不需要在编写mybatis-config.xml配置文件,简化了开发。 1. 首先需要引入依赖 spring依赖 mybatis依赖 mybatis-spring依赖 mysql依赖 druid依赖 2. 编写sprin...

weixin_44837750的博客 490

解决VNC Viewer连接Ubuntu桌面异常:从灰屏到完整菜单栏的实战指南

本文详细解析了使用VNC Viewer连接Ubuntu桌面时出现灰屏或菜单栏缺失的常见原因及解决方案。从桌面环境冲突到配置文件错误,提供了彻底清理系统残留配置、重新安装纯净桌面环境、优化xstartup文件配置等实战步骤,帮助用户快速恢复完整的远程桌面体验。

weixin_30892037的博客 83

从0到1搭建StarRocks3.4.1存算一体架构(VM 虚拟机版)

本文详细介绍了如何在VM虚拟机上从零搭建StarRocks 3.4.1存算一体架构。首先阐述了StarRocks作为高性能分布式SQL数据仓库的优势,重点讲解了其存算一体架构的设计原理。随后提供完整的安装指南,包括环境准备(3台CentOS 8虚拟机配置)、网络互通验证、Java环境配置、软件包解压安装等关键步骤。文章特别详细说明了FE和BE节点的配置文件修改(fe.conf和be.conf)以及必要的防火墙端口开放配置。通过图文并茂的方式,帮助开发者和运维人员快速掌握StarRocks集群部署方法,为后续

小 tom的博客 1330

mybatis之依赖于spring初始化过程分析

写在前面 通过这里文章我们分析了mybatis自身的初始化等相关内容,其中有加载全局配置文件->加载全局配置文件中的mappers信息->加载mapper文件中的stament等初始化相关流程,对应的主要类的初始化为“通过全局配置文件创建SqlSessionFactory->通过openSesion创建SqlSession”,之后就可以通过SqlSession创建Mapper进行数据库操作了,当和spring整合之后,初始化依然是这些内容,创建的也依然是这些类,只不过配置的方式稍有改变,加

wang0907的博客 634

项目过程记录:ADS-B信号接收并显示(Ubuntu20.04+ANTSDR E310V2)

最近被安排做一个ADS-B信号接收的项目,拿到软件无线电模块(ANTSDR E310V2)后安装环境和软件真的太折磨了。。在此记录以下我走过的弯路,大家可以参考一下。

weixin_43627638的博客 5018

MyBatis的通俗理解:SqlSession.getMapper()源码分析

一、什么是 MyBatis? 直接看官方文档:https://mybatis.org/mybatis-3/zh/index.html。 从上面我们了解到: 1、MyBatis 是一款优秀的持久层框架 2、MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 3、MyBatis 避免了几乎所有的 JD...

LinDongTian 2万+

C# 实现鼠标轨迹录制与回放自动化功能(附源码)

通过本文的介绍,相信大家已经掌握了鼠标轨迹录制与回放功能的实现方式。该功能在自动化测试和重复性工作中具有重要应用价值。后续可以进一步优化,增加更多扩展功能,形成一个完整的自动化工具。

weixin_72139050的博客 1756

音视频开发基础(1):模拟视频技术简介

模拟视频技术是指用模拟技术对动态影像进行捕捉、记来、处理、存储、传输、复现的技术.模拟视频技术的发明、发展与模拟电视系统的发展密不可分.下面将通过模拟电视系统来介绍模拟视频技术中的基本概念. 首先,人的视觉系统的特征为电视等視稿系铳的发明、发展提供了理论依据.光线通过角膜、腫孔、晶状体的折射光线.透过玻璃体到达视网展.视网膜上分布着光感受器,光感受器在光线的剌激下...

琅嬛福地 1493

MyBatis 源码分析--获取SqlSession

前文我们从源码层面梳理了 SqlSessionFactory 的创建过程,本篇我们继续分析一下 SqlSession 的获取过程。

weixin_42118323的博客 2212

SAP_SD模块销售利润中心替代简介

SAP SD模块跨公司销售利润中心替代简介 在SAP SD模块中,系统自动生成的财务凭证需要正确反映利润中心归属。当默认利润中心取值不符合业务逻辑时(如跨公司销售、多组织共用工厂等情况),需配置利润中心替代功能。该功能通过事务码0KEM定义替代规则,可根据物料、客户等条件自动替换利润中心字段。系统配置包括创建替代规则、定义先决条件、设置用户出口程序等步骤。对于复杂业务场景,还可通过用户出口或BADI增强实现。利润中心替代能确保销售收入与成本正确核算,避免利润分配错误,满足企业多维度利润分析需求。

我小时候很黑的博客 437

Mybatis源码SqlSession源码分析

前面简单的写了个mybatis的demo运行,并且根据demo运行了解了mybatis的执行流程,其实mybatis的源码还是很简单的,看过Spring之后就会感觉看其他框架的源码就是福利啊,在mybatis的执行流程中有很多经常听到或者面试被问到的几个类,尤其是SqlSession,本文将对SqlSession的执行进行简单的分析。

李永志的博客 3142

手把手教你学simulink实例--基于Simulink的轨道交通车辆悬挂系统仿真

轨道交通车辆悬挂系统是保证列车运行平稳性、舒适性和安全性的重要组成部分。通过悬挂系统的合理设计,可以有效减小车辆在运行过程中受到的轨道不平顺和振动影响。基于MATLAB/Simulink平台进行悬挂系统仿真,可以对悬挂系统的动力学行为、控制策略以及性能优化等环节进行建模与分析,从而验证系统的设计性能并优化参数。本项目旨在构建一个完整的轨道交通车辆悬挂系统仿真模型,包括悬挂系统动力学建模、控制策略模块以及性能评估模块,并通过仿真验证系统的稳定性和舒适性。

MHD0815的博客 1034

《低功耗方法学》翻译——前言

前言

记录所学,分享知识,结识挚友 1208

MyBatis源码剖析之Configuration、SqlSession、Executor、StatementHandler细节

MyBatis是一个流行的持久化框架,用于在Java应用程序中简化与关系数据库的交互。了解MyBatis的核心组件对于深入理解它的工作原理非常重要。Configuration(配置对象)对象是MyBatis的配置类,负责管理MyBatis的全部配置信息。它包含了数据源(DataSource)、类型处理器(TypeHandler)、Mapper映射文件(Mapper XML)、全局设置(settings)、插件(plugins)等。

write less , do more 3862

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

MyBatis核心源码解析 从SqlSession到Mapper接口的绑定过程

摘要:本文深度解析MyBatis框架的核心原理与最佳实践。从架构总览、SqlSession创建机制到Mapper动态代理实现,详细剖析了SQL执行链路、缓存机制和插件原理。通过源码分析揭示MyBatis内部工作原理,包括Configuration加载、Executor调度和StatementHandler执行过程。针对常见性能问题提供优化方案,如批量操作、分页查询和缓存使用技巧。最后总结企业级开发中的"MyBatis军规",包括SQL编写规范、缓存策略和监控方案,帮助开发者规避典型陷阱,

七夜zippoe的博客 2150

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Mybatis的核心——SqlSession解读

在spring中,dao层大多都是用Mybatis,那么 1,Mybatis执行sql最重要的是什么? 在以前对Mybatis的源码解读中,我们知道,Mybatis利用了动态代理来做,最后实现的类是MapperProxy,在最后执行具体的方法时,实际上执行的是: @Override public Object invoke(Object proxy, Method method, Obj...

一个想写小说的程序员 1万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

MyBatis源码分析——使用SqlSession操作数据库

文章目录MyBatis源码分析使用SqlSession操作数据库SqlSession自带方法整体操作流程相关参考 MyBatis源码分析 使用SqlSession操作数据库 MyBatis执行数据库操作主要分为三种:使用SqlSession自带方法、调用Mapper接口方法执行SQL、使用注解执行SQL SqlSession自带方法 在示例代码中使用了SqlSession.selectOne()方...

SK_Jaco的博客 3378

MyBatis源码分析(三)SqlSession的执行主流程

PreparedStatementHandler:预编译语句处理器,继承 BaseStatementHandler 抽象类,对应 java.sql.PrepareStatement 对象的处理,相比上面的普通语句处理器,它支持可变参数 SQL 执行,由于 PrepareStatement 的特性,它会进行预编译,在缓存中一旦发现有预编译的命令,会直接解析执行,所以减少了再次编译环节,能够有效提高系统性能,并预防 SQL 注入攻击(所以是系统默认也是我们推荐的语句处理器)。处理存储过程执行后的输出参数;

秃了也弱了 909

MyBatis 源码分析之 SqlSession 创建

内容来自【自学星球】欢迎大家来了解我的星球,和星主(也就是我)一起学习 Java ,深入 Java 体系中的所有技术。我给自己定的时间是一年,无论结果如何,必定能给星球中的各位带来点东西。

技术分享、唠嗑水文、如有不周、还望海涵 1069

Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析

Mybatis流程步骤 a.获取SqlSessionFactory对象 b.获取SqlSession对象 c.获取Mapper对象(代理接口中的方法、mapper.xml中的标签) d.执行标签中定义的SQL语句 SqlSessionFactory String resource = "conf.xml"; InputStream inputStream = Resources.getRe...

zjj_daniu的博客 1万+

MyBatis源码分析——MyBatis核心组件和开启SqlSession

文章目录MyBatis源码分析MyBatis核心组件MyBatis示例代码开启SqlSessionSqlSessionFactoryBuilder.build()方法SqlSessionFactory.openSession()方法开启SqlSession方法调用链 MyBatis源码分析 MyBatis核心组件 MyBatis有几个非常重要的接口和类:Configuration、SqlSessi...

SK_Jaco的博客 1030

Mybatis源码分析五之SqlSession

一、SqlSession 第一节我们知道,Mybatis执行sql语句的时候都是通过SqlSession来执行的,从第二节我们分析了SqlSessionFactory,也就是不断的产生SqlSession的工厂类,只需要调用其openSession方法即可。 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {

solayang的博客 299

源码分析——MyBatis核心接口SqlSession的实现原理

在上一篇文章中(《MyBatis动态代理调用过程源码分析》),我们知道了MyBatis动态代理的核心是MapperProxy,在它内部封装了动态代理的调用逻辑,而我们也知道了在使用动态代理进行操作的时候实际上还是调用的SqlSession中的API去实现的,那么我们今天就来分析一波SqlSession的源码,由于SqlSession中方法很多,我们就已查询方法为例进行分析。 一. 核心接口SqlS...

听得到微笑的博客 1797
上一篇: ORM framework源码分析:引言之Java JDBC
下一篇: Mybatis3源码分析(二):扫描Mapper关联到spring IOC容器
闲庭细步
博客等级 码龄18年 304粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值