首页  

mybtais mybatisplus TkMybatis 原理     所属分类 mybatis 浏览量 66
Mybatis源码分析

解析过程
根据mybatis-config.xml创建通过SqlSessionFactoryBuilder创建SqlSessionFactory对象
通过XPathParser解析器来帮助解析xml
XMLConfigBuilder解析config.xml
XMLMapperBuilder解析Mapper.xml
XMLStatementBuilder解析select等sql语句
最终的语句包装类为MappedStatement
SqlSessionFactory对象其中包含一个完整的Configuration对象
Configuration对象中的字段mappedStatements保存语句,key为类路径+sql的Id
sqlSessionFactory.getConfiguration().getMappedStatementNames();
["org.demo.dao.mapper.PetMapper.queryPets","queryPets"]


mapperRegistry保存所有解析的Mapper接口
每次向mapperRegistry中添加Mapper接口时,会尝试查找相同包名下的mapper.xml文件


执行过程
通过SqlSessionFactory对象创建SqlSession对象,具体类型为DefaultSqlSession
其中包含一个执行器Executor,经过了拦截器的处理
通过SqlSession对象获取Mapper对象,底层使用JDK动态代理
拦截器为MapperProxy对象
通过方法获取一个MapperMethod对象,其中包含MappedStatement
通过MappedStatement创建一个BoundSql对象
BoundSql对象包含要执行的sql和参数等信息
创建一个StatementHandler,其中通过DefaultParameterHandler来设置参数
最终通过PreparedStatement执行
通过DefaultResultSetHandler来处理返回值,先处理列名属性自动映射,再处理配置的ResultMap,具体逻辑在 getRowValue() 方法。

关于SQL语句中的${}和#{}的处理
MappedStatement中包含一个SqlSource对象
DynamicSqlSource 
RawSqlSource 
ProviderSqlSource 
StaticSqlSource

RawSqlSource     只有 #{} 或者 没有标签的纯文本sql信息
DynamicSqlSource 包含 ${} 或者 具有动态sql标签的sql信息
StaticSqlSource  是DynamicSqlSource和RawSqlSource解析为BoundSql的一个中间环节




在MappedStatement获取BoundSql对象时,会将#{}转换成?,并将之前的SqlSource对象转换成StaticSqlSource类型。
对于${}的处理(需要手动加单引号),具体处理类为TextSqlNode的apply()方法,拼接SQL(通过OGNL表达式获取属性值),
对于#{}的处理,是PreparedStatement设置参数(防止SQL注入)。
orderby只能使用${}。
SqlSourceBuilder来解析#{uname,jdbcType=VARCHAR}这种表达式语法。

select * from tb_user where u_name like '${uname}'; -- 需要加单引号
select * from tb_user where u_name like #{uname};
关于默认参数名称
select * from tb_user where u_name like #{param1} and u_age = #{param2};
具体处理类为ParamNameResolver

关于like的使用
select * from tb_user where u_name like concat('%', #{uname}, '%');
需要在 sql 中拼接 % 或者代码中拼接 %

懒加载
Configuration的lazyLoadingEnabled字段,默认false,proxyFactory默认使用JavassistProxyFactory创建代理,也支持Cglib。
在创建ResultMap时可能使用。

缓存
一级缓存:BaseExecutor的localCache字段,内部为HashMap,同一个SqlSession(因为不同的SqlSession包含不同的Executor)。
默认开启,增删改会清空缓存。

二级缓存:SqlSessionFactory级别

< settings>
    


< cache />

存储在Configuration的caches字段中,key为Mapper.xml的namespace
也会存储到MappedStatement的cache字段中

主要是TransactionalCacheManager的transactionalCaches字段来管理,
key为Cache类型,value为TransactionalCache类型(包装了Cache),必须commit之后缓存才实际保存到Cache中。
入口类为CachingExecutor。
从MappedStatement中获取Cache对象
根据此对象从TransactionalCacheManager中获取对应的TransactionalCache
查询是否有缓存值
有则直接返回,没有走一级缓存的流程
保存到TransactionalCache对象中
commit之后,保存到TransactionalCache中的delegate字段中,实际是委托它来存储的。

分页插件 pagehelper


< plugins>
  < plugin interceptor="com.github.pagehelper.PageInterceptor" />

PageHelper.startPage(1,2);


将分页信息保存到ThreadLocal中,实际上是一个Page对象。
拦截BaseExecutor的query()方法
生成一个count的sql并执行(通过jsqlparser解析原来的sql)
将查询得到的数据总数量count也保存到Page中
对原来的查询SQL拼接分页信息,如mysql拼接limit
将查询得到的list结果也保存到Page中
最终返回的就是Page对象

整合SpringBoot
mybatis-spring-boot-starter
配置Mapper.xml路径
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
配置Mapper接口扫描包路径
@SpringBootApplication
@MapperScan("com.xxx.mybatis")

或者对Mapper接口添加@Mapper注解,最终创建的Mapper实现类为MapperFactoryBean
会自动装配MybatisAutoConfiguration,自动配置SqlSessionFactory,SqlSessionTemplate,
最终使用的 SqlSession 实现为动态代理,拦截器为 SqlSessionInterceptor

@MapperScan 
ClassPathMapperScanner  将Mapper接口的实现(MapperFactoryBean)注入了Spring容器中 

原理图
https://gitee.com/dyyx/work2024/tree/master/docs/mybatis/images/

mybatis001.webp   mybatis002.webp  mybatis003.webp


MybatisPlus源码分析 解析过程 使用MybatisSqlSessionFactoryBuilder替代原来的SqlSessionFactoryBuilder 使用MybatisXMLConfigBuilder替代原来的XMLConfigBuilder 使用MybatisConfiguration替代Configuration 使用MybatisMapperRegistry替代MapperRegistry 使用MybatisMapperProxyFactory替代MapperProxyFactory 使用MybatisMapperProxy替代MapperProxy 使用MybatisMapperAnnotationBuilder替代MapperAnnotationBuilder 使用GlobalConfig保存全局配置 如果接口类是com.baomidou.mybatisplus.core.mapper.Mapper的子类, 使用ISqlInjector注入动态SQL的实现,可以自定义自己的SQL注入器 执行过程 使用MybatisCachingExecutor替代CachingExecutor 重写query()方法,支持分页查询 使用PaginationInterceptor插件 拦截BaseStatementHandler的prepare()方法 生成一个count的SQL 使用拦截的方法参数 执行count的SQL MybatisPlus默认开启类名和表名的转换(属性和列名),驼峰转下划线,具体处理类为TableInfoHelper 特性 内置通用mapper,可以很方便的实现单表的大部分增删改查操作。 PaginationInterceptor用来处理类型为IPage的参数,MybatisMapperMethod用来处理返回类型为IPage的返回值 MetaObjectHandler用来在insert或update时自动设置属性值, 配合注解@TableField的fill字段使用,在MybatisParameterHandler处理参数时生效。 注解@TableLogic,标注此注解的属性,调用内置的删除方法时,不是真正的delete,而是update,内置select时默认加上此条件。 注解@EnumValue,配合MybatisEnumTypeHandler处理器 IPage< User> findByPage(IPage< User> page); //页码从1开始
TkMybatis源码分析 解析过程 MapperAutoConfiguration开启自动配置,在MybatisAutoConfiguration之前生效 定义SqlSessionFactory和SqlSessionTemplate 使用注解@tk.mybatis.spring.annotation.MapperScan 替代 @org.mybatis.spring.annotation.MapperScan 它的解析类MapperScannerRegistrar内部使用新的 tk.mybatis.spring.mapper.ClassPathMapperScanner替代老的org.mybatis.spring.mapper.ClassPathMapperScanner 将Mapper接口的实现类替换为 tk.mybatis.spring.mapper.MapperFactoryBean, 代替老的 org.mybatis.spring.mapper.MapperFactoryBean 新的MapperFactoryBean重写了checkDaoConfig()方法,处理配置的子接口 mapper.mappers=tk.mybatis.mapper.common.Mapper 获取方法上的SelectProvider,UpdateProvider,DeleteProvider,InsertProvider注解信息, 生成SqlSource对象,并设置到MappedStatement对象中 接口继承 tk.mybatis.mapper.common.Mapper接口 拥有增强功能 本质上利用了mybatis本身提供的Provider功能(通过Provider来自定义sql) 通过 EntityHelper 来解析 javax.persistence 包下的 @Table,@Id,@Column等注解, 保存实体类和表结构的映射关系,功能类似 mybatisplus 的 TableInfoHelper 类

上一篇     下一篇
小红书视频下载

羽毛球新手学习顺序

mybtais 动态sql注解

java final 字段 反射修改说明

煎荷包蛋小技巧

mac brew 安装 openjdk17