Mybatis
2023-12-26 18:56:06 27 举报
AI智能生成
Mybatis
作者其他创作
大纲/内容
简介
优缺点
优点
配置使用连接池简单
SQL语句写在配置文件中与java代码分离,支持态SQL
自动映射java对象和sql语句
与JDBC比较代码量减少
缺点
SQL编写工作量大
sql语句依赖数据库,项目移植性降低,不能随意变更数据库
与其他方式比较
与jdbc比较
jdbc
需要自己实现连接池
PreparedStatement使用占位符传参,存在硬编码
对结果集的处理存在大量重复代码
mybatis
集成连接池简单
在xml配置文件中写SQL,实现与java代码分离
自动映射java对象与SQL语句
与hibernate比较
hibernate
全变映射框架
提供了日志、缓存、级联(更强大)等特性,数据库无关性更好(但会消耗更多的性能)
重量级框架,学习成本高,适合需求相对稳定的项目
Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。
mybatis
半自动映射框架
支持动态SQL,处理列表,动态生成表名,支持存储过程,但工作量相对大些
不支持数据库无关,但SQL优化相对简单
MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架
映射器
#{}与${}传参的区别
#{}
占位符预编译阶段处理
变量替换在DBMS中进行
${}
字符串替换,不需要预编译处理
变量替换在DBMS之前进行
Like语句查询
1.直接编码硬拼接
’%${question}%’
会有SQL注入风险不推荐
"%"#{question}"%"
2.CONCAT()函数
CONCAT('%','***','$')
3.bind标签
<select id="listUserLikeUsername" resultType="com.jourwon.pojo.User">
<bind name="pattern" value="'%' + username + '%'" />
select id,sex,age,username,password from person where username LIKE #{pattern}
</select>
<bind name="pattern" value="'%' + username + '%'" />
select id,sex,age,username,password from person where username LIKE #{pattern}
</select>
传递多个参数
1.顺序传参
2.@Param注解
3.Map对象
4.Java Bean
批量操作
<foreach>
使用ExecutorType.BATCH
主键生成方式
1.<insert id="insertUser" useGeneratedKeys="true" keyProperty="userId" >***</insert>
2.<selectKey keyColumn="id" resultType="long" keyProperty="id" order="BEFORE">***</selectKey>
执行器(Executor)
BaseExecutor
三种基本执行器
SimpleExecutor(Mybatis默认使用)
每次使用开启Statement对象,用完即关闭
ReuseExecutor
以SQL id为键查找Statement对象,没有才创建。使用后不关闭
BatchExecutor
将所有语句添加到批处理中,统一执行
不足:在insert时,事务未提交之前不能获取自增长ID
不支持select的批处理(JDBC批处理不支持select)
严格限制在sqlSession生命周期范围内
作用范围
严格限制在SQL Session生命周期返回内
概述
在mybatis配置文件中可以单独指定使用的执行器,在开启用session会话的时候配置
可以在全局配置中设置执行器,但不建议这么做
CachingExecutor
和缓存相关,二级缓存会先从这获取数据,未命中才去数据库查询
参考:https://blog.csdn.net/zongf0504/article/details/100104029
延迟加载
仅支持关联类型(嵌套查询)的延迟加载
原理
使用CGLIB创建对象的代理对象
Mapper编写方式
1.接口实现类继承 SqlSessionDaoSupport:使用此种方法需要编写mapper 接口,mapper 接口实现类、mapper.xml 文件。
2.使用 org.mybatis.spring.mapper.MapperFactoryBean
3.使用 mapper 扫描器
运行原理
编程步骤
1.创建SqlSessionFactory
2.通过SqlSessionFactory创建SqlSession
3.通过SqlSession执行数据库操作
4.调用session.commit()提交事务
5.调用session.close()关闭session
工作原理
1.读取mybatis全局配置文件(mybatis-config.xml),其中包含了运行环境等信息
如:数据库连接信息等
2.加载全局配置文件中配置的SQL映射文件
3.通过运行环境等配置构建会话工厂(SqlSessionFactory)
4.通过会话工厂创建会话对象
包含了执行SQL语句的所有方法
5.执行器(Executor)操作数据库
通过session传递的参数动态的生成要执行的SQL语句,同时负责查询缓存的维护
6.MappedStatement
执行器接口中有一个MappedStatement参数,该参数是对映射信息的封装,用于存储要映射sql的Id和参数等信息
每一个<select> 、<insert> 、<update> 、<delete> 标签,都会被解析为一个MappedStatement对象。
7.输入参数映射
8.输出参数映射
架构功能
API接口层
对外提供使用;已接收到请求就转发给数据处理层处理
主要接口
数据增加接口
数据查询接口
数据修改接口
数据删除接口
接口调用方式
基于Statement ID
基于Mapper接口
数据处理层
负责Sql的查找,解析,执行和结果映射,主要完成一次数据库操作
主要操作
1.参数映射
2.SQL解析
3.SQL执行
4.结果集映射
基础支持层
负责基础功能支持
事务管理
连接池管理
缓存机制
SQL配置方式
注解
xml
引导层
基于xml配置方式
基于java API 方式
预编译
在发送语句在DBMS之前对sql进行编译,不需要SBMS进行编译
优点
预编译阶段可以合并多次SQL操作为一次
编译语句对象可以重复利用,把一个SQL语句编译产生的PreparedStatment对象缓存下来,下次可以直接使用
mybatis默认对所有SQL进行预编译
防止SQL注入
高级查询
一对一
一对多
查询方式
一对多
查询方式
关联查询
嵌套查询
枚举(Enum)支持
自定义实现TypeHandler实现类型映射
动态SQL
trim|where|set|foreach|if|choose|when|otherwise|bind
分页
分页方式
使用RowBounds对象进行内存分页(假分页)
分页原理
用Mybatis提供的插件接口,
实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
mybatis支持插件
可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件
缓存
一级缓存
会话级缓存,会话结束即清空
对其他session对数据的CUD操作无法感知
基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session
是一个粗粒度的缓存,没有更新缓存和缓存过期的概念,同时只是使用了默认的hashmap,也没有做容量上的限定
对统一SQL的认定Key为:Statement Id + Offset + Limmit + Sql + Params
有多个SqlSession或者分布式的环境下,有操作数据库写的话,会引起脏数据,建议是把一级缓存的默认级别设定为Statement,即不使用一级缓存
二级缓存
存储作用域为 Mapper(Namespace)
默认不打开二级缓存
使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置、<cache/> ;
多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用的条件比较苛刻
分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将Mybatis的Cache接口实现,有一定的开发成本,不如直接用Redis,Memcache实现业务上的缓存就好了。
注意事项及解决办法
由于二级缓存基于namespace缓存,如果在另外一个namespace更改了数据是无法感知的,因此建议在同一个namespace下处理CRUD。
解决办法:
<cache-ref namespace="*。*。*Mapper"/>
cache-ref代表引用别的命名空间的Cache配置,两个命名空间的操作使用的是同一个Cache。不过这样做会使缓存粒度变粗,如果关联较多就失去了缓存的意义。
解决办法:
<cache-ref namespace="*。*。*Mapper"/>
cache-ref代表引用别的命名空间的Cache配置,两个命名空间的操作使用的是同一个Cache。不过这样做会使缓存粒度变粗,如果关联较多就失去了缓存的意义。
更新机制
当某一作用于进行CUD操作后,其下所有select缓存清空
数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。
其他
接口绑定方式
在接口方法上加@select @Update等注解
通过xml方式,指定namespace与接口类关联
接口调用时注意事项
Mapper接口方法名和mapper.xml中定义的每个sql的id相同。
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。
Mapper.xml文件中的namespace即是mapper接口的类路径。
Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个
MappedStatement
MappedStatement
接口方法不能重载
XML文件与Mybatis内部对象对应关系
1.Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。在Xml映射文件中,
2.<parameterMap> 标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。
3.<resultMap> 标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个
4.<select> 、<insert> 、<update> 、<delete> 标签均会被解析为MappedStatement对象,
5.标签内的sql会被解析为BoundSql对象。
2.<parameterMap> 标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。
3.<resultMap> 标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个
4.<select> 、<insert> 、<update> 、<delete> 标签均会被解析为MappedStatement对象,
5.标签内的sql会被解析为BoundSql对象。
参考文献:
https://www.jianshu.com/p/c553169c5921
https://thinkwon.blog.csdn.net/article/details/101292950
https://www.jianshu.com/p/c553169c5921
https://thinkwon.blog.csdn.net/article/details/101292950
你真的会用Mybatis的缓存么,不知道原理的话,容易踩坑哦
0 条评论
下一页