MyBatis理论与实践
2022-03-05 01:18:40 5 举报
AI智能生成
MyBatis理论与实践
作者其他创作
大纲/内容
1. 频繁创建释放数据库连接、数据库配置信息硬编码
2. sql语句、设置参数、获取返回结果集参数存在硬编码
3. 手动封装返回结果集
JDBC问题
连接池:解决频繁创建释放数据库连接
配置文件:解决硬编码
反射、内省:解决手动封装返回结果集
解决思路
(1)引入依赖(2)编写配置文件 sqlMapConfig.xml:存放数据库配置信息 mapper.xml : 存放sql配置信息
使用端
自定义持久层框架本身
持久层框架设计思路
修改:sqlSession接口及实现类DefaultSqlSession 方法:getMapper(Class<?> inferfaceClass) 总结:底层是JDK动态代理,返回接口的代理对象 代理对象调用接口中任意方法,都会执行invocationHandler接口实现类的invoke方法 invoke方法中:调用的还是sqlSession的crud方法
优化(mapper代理)
一:自定义持久层框架
ORM:Object/Relation Mapping:对象关系映射: 让实体类和表产生映射关系:把对持久化对象的保存、修改、删除等操作,转换为对数据库的操作
MyBatis 是一款优秀的基于ORM的半自动轻量级持久层框架
基本概念
environments:数据源环境配置标签
resource属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下resource=\"jdbcConfig.properties\"
properties: 属性配置
<!-- 单个别名定义 -->;<typeAlias alias=\"user\"; type=\"com.lagou.pojo.User\">;
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --><package name=\"com.lagou.domain\"/>;
typeAliases:自定义别名
方式一:<mapper resource=\" \" />使用相对于类路径的资源如:<mapper resource=\"com/lagou/dao/IUserDao.xml\" />
方式二:<mapper class=\" \" />使用 mapper 接口类路径如:<mapper class=\"com.lagou.UserMapper\"/>注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中
方式三:<package name=\"\"/>注册指定包下的所有 mapper 接口如:<package name=\"com.lagou.mapper\"/>注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中
mappers:映射器
注意问题:1.条件判断中不能使用&&,要使用and 2.<if>标签的 test 属性中写的是对象的属性
<if test=条件判断></if>
<where></where>
<foreach>标签用于遍历集合collection: 代表要遍历的集合元素,注意编写时不要写#{}open: 代表语句的开始部分close: 代表结束部分item: 代表遍历集合的每个元素,生成的变量名separator: 代表分隔符
<foreach> </foreach>
<sql id=\"defaultSql\"> select * from user</sql>
抽取重复的语句代码片段
include refid=\"defaultSql\"></include>
使用
<select>
动态sql
配置文件
实体中表示一方关系:实体
使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。 <association property=\"user\" javaType=\"com.lagou.pojo.User\">
一对一
实体中表示多方关系:集合
使用 resultMap,定义专门的 resultMap 用于映射一对多查询结果。 <collection property=\"orderList\" ofType=\"com.lagou.pojo.Order\">
一对多
双方实体中表示对方关系:集合
多对多
复杂映射
@Insert:实现新增@Update:实现更新@Delete:实现删除@Select:实现查询@Result:实现结果集封装@Results:可以与@Result 一起使用,封装多个结果集@One:实现一对一结果集封装@Many:实现一对多结果集封装@CacheNamespace:实现注解二级缓存的使用
常用注解
代替的是标签<resultMap>
@Results 注解
id 是否是主键字段column 数据库的列名property 需要装配的属性名one 需要使用的@One 注解(@Result(one=@One)()))many 需要使用的@Many 注解(@Result(many=@many)())
代替了 <id> 标签和<result> 标签
@Result 注解
select 指定用的 来多表查询的 sql mapperfetchType 会覆盖全局的配置参数 lazyLoadingEnabled取值:\teager lazy default
代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
@One 注解(一对一)
代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
@Many 注解(多对一)
复杂关系映射的注解说明
注解开发
缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存, 我们可以避免频繁的与数据库进行交互, 进而提高响应速度
缓存概念
sqlSession级别
存储作用域
基于 PerpetualCache 的 HashMap 本地缓存
底层数据结构
失效情况
一级缓存
namespace(跨sqlSession)
底层数据结果
生效:当sqlSession执行commit或者close会情况一级缓存,将缓存内容存到二级缓存
对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
问题:关于mybatis二级缓存的一些考虑,例如集成redis实现分布式环境下的缓存,情况一:如果当前应用如果是更新操作多过查询操作,就会出现频繁删除缓存操作;情况二:连表查询会有问题,该如何考虑二级缓存?
二级缓存
缓存原理
理解:类似拦截器,对四大对象进行拦截,用来增强核心对象的功能,本质上是借助底层的动态代理实现的
执行器ExecutorSQL语法构建器StatementHandler参数处理器ParameterHandler结果集处理器ResultSetHandler
拦截方法:
<plugins> <plugin interceptor=\"com.lagou.plugin.MySqlPagingPlugin\"> <!--配置参数--> <property name=\"name\" value=\"Bob\"/> </plugin></plugins>
自定义插件
①导入通用PageHelper的坐标②在mybatis核心配置文件中配置PageHelper插件③测试分页数据获取
pageHelper
① 引入mapper的依赖②Mybatis配置文件中完成配置③实体类设置主键③定义通用mapper
通用mapper
常用插件
插件机制
二:基础回顾及高级应用
API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理
数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作
基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑
功能架构分层
总体流程
架构原理
源码分析
三:源码分析及设计模式
第一部分:mybatis模块回顾
问题: 请完善自定义持久层框架,在现有代码基础上添加修改及删除功能思路:(1) 修改XMLMapperBuilder的parse方法:解析<update><delete>标签(2) 在SqlSession及DefalutSqlSession添加update及delete方法(3) 在getMapper方法中对当前执行的sql语句进行判断,决定调用增删改查的那个方法(4) 在Executor及simpleExecutor中添加update及delete方法
第二部分:Mybatis思路分析
mybatis collection 如何解决n+1问题(批量查询sql,many 一方会产生 n次io查询请求)
在一对多返回结果集映射中,为什么collection的映射主键属性使用<id>就只会返回一条记录,而使用<result>就可以返回多条记录。
#和$的区别和联系
为什么mapper中paramterType不能设置为对象属性的类型,如User中int型属性id,paramterType设成Integer,执行时报反射异常。
既然有一级缓存、二级缓存,为什么还要用redis做缓存呢?
CachingExecutor对二级缓存的实现原理和存储过程?以及一二级缓存的协调互斥性?
当库表外键字段与对应表主键字段一样时,resultMap里的column该怎么设置
介绍下mybatis的日志模块,工作原理,如何利用日志进行排障
xml与注解方式的开发各有利弊。注解方式每次改了sql都要重新编译,这种模式方便了开发,真正开发中是否可取?
jdbc批量插入10000条数据跟在一个session中执行10000次插入,有区别吗?
sqlsession线程安全与不安全?并发情况如何保证线程安全?
通过注解的方式完成crud,传递多个参数,能否做一下演示?
sql注入是怎么一回事?使用mybatis哪些地方要防止sql注入?
pageHelper对于一对多分页嵌套结果集的方式会分页不准确,不使用嵌套子查询(效率太低),有什么好的解决方案吗,如自定义一对多分页的思路等
Mybatis如何执行批处理?
mybatis插件在实际项目中具体有哪些应用,多举些例子吧,像记录操作日志或数据埋点适合使用吗?
用PerpetualCache作为二级缓存应该有线程安全问题吧
sqlsessionFactoryBuilder采用的是建造者模式还是策略模式?
自定义的插件不需要一个执行顺序吗?
动态sql中是如何解析每个节点,在mappedstatement中是以何种形式存储的?
mybatis在插入过程中主键的生成原理,以及过程。
使用注解开发的时候如果牵扯的表多的话,或者是SQL复杂的话,感觉不如直接使用SQL简单明了;
二级缓存开启后,一级缓存还存在吗?源码中从一级缓存取数据时好像并没有判断二级缓存是否开启
一级缓存,某张表执行更新操作后,是所有表的缓存失效,还是只有相关表的缓存失效?
mybatis中配置事务管理类型为“JDBC”,底层具体事务是怎么控制实现的?
Mybatis是怎么实现延迟加载的,它背后的原理是什么?
模板方法模式和策略模式区分不清。
MyBatis 的 mapper 接口调用时有哪些要求?
在部分公司的实战环境中不推荐甚至禁止$出现在映射xml中,核心原因是什么?仅仅是因为SQL注入导致的安全问题?
mybatis-plus在项目中的选型是否可以考虑,和mybatis相比有什么好的地方
如何对mybatis进行性能调优?从哪几个方面入手?
第三部分:mybatis若干问题
MyBatis
收藏
收藏
0 条评论
下一页