Mybatis源码总结

发布时间:2024年01月19日

mybatis

Mybatis是一个orm框架,帮助我们更好的在java中编写和管理SQL语句
主要的运行过程:

  1. 主配置文件,配置mapper文件的位置,以及数据源,缓存,插件等配置信息,项目运行起来后会解析该文件,相关信息存储在Configuration对象中
  2. mapper文件,写sql,与mapper接口对应起来,实现sql和java代码分离,通过解析,会保存在Configuration对象中,key:全路径类名+方法名 ,value:MappedStatement对象,里面包含该方法sql的各种信息,二级缓存在该对象中
  3. sqlSession是主要的类,用来执行sql的增删改查,要生成它需要一个SqlSessionFactory工厂类,生产出来的sqlSession实现类DefaultSqlSession,其中一级缓存就是在这个类中
  4. sqlSession执行增删改查操作;也可以通过获取Mapper接口,通过接口来进行sql方法调用,获取到的Mapper接口是通过jdk的动态代理生成代理对象完成的,主要的动态代理逻辑在MapperProxy类中,然后通过调用sqlSession的增删改查方法进行sql执行。
  5. 下面介绍sqlSession的实现类DefaultSqlSession的select方法过程涉及到的重要类以及过程
    1. Executor:SqlSessionFactory的openSession在创建Executor的时候会把插件对应的拦截了该类中的方法进行动态代理,完成增强,该执行器的作用是生成sql语句(**MappedStatement 中的语句生成工具 **通过xml中写的sql是否有需要填充属性的分为动态sql和原始sql),以及一二级缓存的获取和更新,在这里通过Transaction获取数据库连接
    2. StatementHandler:也可以通过插件 进行拦截的方法,会创建ResultSetHandlerParameterHandler然后通过connection创建生成jdbc的PreparedStatement,然后调用parameterHandler填充参数
    3. ParameterHandler:使用paredStatement的setxxxx方法填充参数,在填充的时候要知道要填充的数据类型对应sql的数据类型,好调用对应的paredStatement的setxxx方法,这个时候需要TypeHandler的各种类型的实现,来调用paredStatement.setxxx方法
    4. 最后执行paredStatement.execute(sql)
    5. ResultSetHandler:处理执行后返回的jdbc的ResultSet,这里也需要TypeHandler处理数据库类型和java类型对应起来,调用对应的实现类的方法,设置给对应的java对象的属性

mybatis-spring

mapper对象注入IOC容器

  1. 通过**@MapperScan**注解导入MapperScannerRegistrar(实现ImportBeanDefinitionRegistrar)->MapperScannerConfigurer(实现的BeanDefinitionRegistryPostProcessor)->**ClassPathMapperScanner#doScan**要扫描所有的mapper接口,beandefinition改成MapperFactoryBean的class,设置MapperFactoryBean的各种属性,比如:当前mapper接口的的全路径类名,SqlSessionTemplate对象
  2. MapperFactoryBean:这是实现了FactoryBean接口,getObject中通过sqlSession#getMapper获取到对应Mapper的动态代理后的对象, 每个Mapper接口都有一个MapperFactoryBean

sqlSessionTemplate:

  1. 里面通过动态代理SqlSessionInterceptor,修改获取SqlSession的逻辑,主要是为了同一个事务线程中可以共用sqlSession,存储在threadLocal中。同时注入几个事务状态感知钩子类(通过TransactionSynchronizationManager.registerSynchronization())
  2. 真正干活的sqlSession还是通过SqlSessionFactory生成DeFaultSqlSession

mybatis-spring和spring事务

在mybatis中,负责事务处理的接口是Transaction(里面设置数据源);主要功能用来获取连接,事务提交和回滚

mybatis和spring整合后不会连接获取和进行提交事务,统一交给spring jdbc中的事务处理。
通过实现了mybatis中Transaction接口的SpringManagedTransaction类,该类中的获取连接又调用spring-jdbc中的工具获取,同时通过isConnectionTransactional属性控制不能再该类中进行提交和回滚,统一把这些回滚和提交工作交给spring事务框架。

spring事务处理大致流程:

  1. 通过TransactionInterceptor拦截器拦截目标方法
  2. 通过DataSourceTransactionManager获取事务,主要获取数据库连接资源并绑定到当前线程中的(TransactionSynchronizationManager),以及参数设置,read only参数会执行sql.
  3. 存储当前事务信息到TransactionInfo.oldTransactionInfo中,事务传播的时候需要
  4. 执行mapper的方法。MapperProxy代理(mybatis-plus中是MybatisMapperProxy); sqlSession是SqlSessionTemplate->SqlSessionInterceptor(动态代理,会通过sqlsession工厂获取sqlSession,并且作为资源绑定到当前线程中,所以同一个事务中可以使用一级缓存
  5. 提交或者回滚事务
    1. 提交事务
      1. triggerBeforeCommit :触发TransactionSynchronization#beforeCommit, 重要实现:mybatis-spring整合中有个SqlSessionUtils.SqlSessionSynchronization.beforeCommit,会执行sqlSession的commit,并不会在这里提交事务(因为事务管理使用了SpringManagedTransaction),只是刷掉sqlSession的缓存等
      2. triggerBeforeCompletion:触发触发TransactionSynchronization#beforeCompletion ,重要实现:mybatis-spring整合中有个SqlSessionUtils.SqlSessionSynchronization.beforeCompletion,会执行sqlSession.close方法,关闭sqlSession
      3. 传播级别嵌套事务的时候,子事务执行的时候,如果有回滚点,释放掉回滚点
      4. 事务执行提交操作,connection.commit()
      5. TransactionSynchronization.afterCommit
      6. 释放资源,数据库连接资源

TransactionSynchronizationManager:管理线程中的事务状态,以及事务资源在线程中的绑定,比如:数据库连接
ResourceHolderSupport:事务中的资源通过该基类,他实现了通过计数方式看当前是否释放资源 ,比如:ConnectionHolder,SqlSessionHolder
TransactionSynchronization: 可以实现钩子函数,在事务执行各个状态可以感知到

事务挂起:就是保留现有的连接,参数信息,等资源,用对象保存起来。然后清空当前线程的资源,重新获取连接

文章来源:https://blog.csdn.net/qq_40836488/article/details/135700534
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。