mybatis相关解析

1. mybatis缓存机制

  • 介绍 : MyBatis 的缓存分为一级缓存和二级缓存,一级缓存放在 session 里面,默认就有,二级缓
    存放在它的命名空间里,默认是不打开的
    ,使用二级缓存属性类需要实现 Serializable 序列化
    接口(可用来保存对象的状态),可在它的映射文件中配置 ** ** 标签即可

  • 一级缓存 : 在一次数据库会话里 用户发起查询时 查询结果会缓存到mybatis的sql session里 该区域结果是一个map 当我们再次查询相同的数据 会直接到该区域查询返回结果 如果没有 则查询数据库

    • 问题 : 如何两次查询一个数据时,中间对这个数据进行了更新操作 怎么办 ???
    在mybatis里在执行更新操作后  会把一级缓存清空
    
    • 手动清理缓存
    使用SqlSession对象调用clearCache()方法    SqlSession.clearCache();
    
  • 二级缓存 : 二级缓存指的是 mybatis中SqlSessionFactory对象的缓存 ,由同一个SqlSessionFactory对象 创建的SqlSession共享缓存

    • 注意 : mybatis的二级缓存SqlSessionFactory中存放的是是数据 而不是对象

2. Mybatis 是如何进行分页的?分页插件的原理是什么?

  • Mybatis 使用 RowBounds 对象进行分页,也可以直接编写 sql 实现分页,也可以使用
    Mybatis 的分页插件

    • **RowBounds ** : 不需要在 sql 语句中写 limit,即可完成分页功能。但是由于它是在 sql 查询出所有结果的基础上截取数据的,所以在数据量大的sql中并不适用,它更适合在返回数据结果较少的查询中使用
  • 分页插件的原理:实现 Mybatis 提供的接口,实现自定义插件,在插件的拦截方法内拦
    截待执行的 sql,然后重写 sql。

    -- 例如 : 
    select * from student
    -- 拦截 sql 后重写为:
    select t.* fromselect * from student)t limit 010
    

3.Mybatis 动态 sql 是做什么的?都有哪些动态 sql?简述一下动态 sql 的执行原理?

  • Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑
    判断和动态拼接 sql 的功能
  • trim / where / set / foreach / if / choose when otherwise / bind。
  • 通过ognl表达式获取sql参数值 根据参数值动态拼接sql语句

3. #{}和${}的区别是什么?

  • **#{}是预编译处理,${}**是字符串替换。

  • Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;

    • PreparedStatement 会把用户的非法传参使用 \ 来标识 以达到防止sql注入问题
  • Mybatis 在处理 时 , 就 是 把 {}时,就是把 {}替换成变量的值。(调用Statement对象)

4.为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?

  • Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象
    时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或
    关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具

5.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?

  • 什么是延迟加载 :

    • 就是在需要用到数据的时候才进行加载,不需要用到数据的时候就不加载数据。延迟加载也称为懒加载
    • 优点:
      • 先从单表查询,需要时再从关联表去关联查询,大大提高数据库的性能,因为查询单表要比关联查询多张表的速度快很多。
    • 缺点:
      • 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也需要耗费时间,所以可能造成用户等待时间变长,造成用户体验下降。
    //例如 : 
    如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。 所以延迟加载即先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
    
  • Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false

  • 原理,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。

6.简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构之间的映射关系?

  • Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。在
    Xml 映射文件中,标签会被解析为 ParameterMap 对象,其每个子元素会
    被解析为 ParameterMapping 对象。标签会被解析为 ResultMap 对象,其每个子
    元素会被解析为 ResultMapping 对象。每一个、、、标签
    均会被解析为 MappedStatement 对象,标签内的 sql 会被解析为 BoundSql 对象。

7.什么是 MyBatis 的接口绑定,有什么好处?

  • 即在mybatis里自定义接口 该接口方法与xml文件的sql语句绑定 我们直接调用接口方法即可实现与数据库交互 比原生是sqlSession方法更加灵活高效

8.接口绑定有几种实现方式,分别是怎么实现的?

  • 注解 : 直接在接口方法上统计@select @delete @update @insert注解 并在注解里写入sql语句实现
  • xml : 指定映射文件 (namespace后添加接口类的全路径实现接口映射) 实现xml自定义sql语句

9.MyBatis 实现一对一有几种方式?具体怎么操作的?

  • 联表查询 : 通过在 resultMap 里面配置 association 属性 实现一对一
  • 嵌套查询 : 先查一个表,根据这个表里面的结果的外键 id,去再另外一个表里面查询数据,也是通过 association 配置,但另外一个表的 查询通过 select 属性配置

10.Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?

  • 使用 resultMap 标签进行逐个映射 如果使用resulttype标签 需要数据库字段和实体类字段一致
  • 使用sql别名进行属性映射

11.Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?

  • sql include 编写可共用的sql语句 使用include标签引入
  • **resultMap ** : 建立 SQL 查询结果字段与实体属性的映射关系信息
  • parameterMap : 一般使用parameterType 即可 用于接受参数
  • selectKey : 为不支持主键自增长的表生成自增长主键
  • 动态标签
    • if : 成立则执行,不成立则不执行
    • choose (when, otherwise) : 类似于java的switch() case语句
    • trim : 截断 添加
      • prefix 在前面添加内容
      • suffix 在后面添加内容
      • suffixOverrides="," : 去掉最后一个 “,”
      • prefixoverride="," : 去掉第一个","
    • foreach : 遍历数组 集合
    • where : sql判断
      • 当编写where标签时,如果内容中第一个是and去掉第一个and
      • 如果 中有内容会生成where关键字,如果没有内容不生成where关键字
    • **set ** : sql修改
      • 去掉最后一个逗号
      • 如果里面有内容就会生成set关键字,没有就不生成
    • bind : 模糊查询
      • 给参数重新赋值

12.当实体类中的属性名和表中的字段名不一样,如何将查询的结果封装到指定 pojo?

  • 使用sql别名功能匹配
  • 使用resultMap标签匹配

13.模糊查询 like 语句该怎么写

  • ‘%${question}%’ 不推荐 存在sql注入风险
  • CONCAT(’%’,#{question},’%’) 推荐
  • NAME like ‘%’|| #{name} || ‘%’
  • 使用bind
<bind name="pattern" value="'%' + _parameter.username + '%'" />
select * from person where username LIKE #{pattern}

14.通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, Dao 的工作原理,是否可以重载?

  • 不能重载,因为通过 Dao 寻找 Xml 对应的 sql 的时候全限名+方法名的保存和寻找策略。
  • 接口工作原理为 jdk 动态代理原理,运行时会为 dao 生成 proxy,代理对象会拦截接口方法,去执行对应的 sql 返回数据。

15.Mybatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问,B 标签能否定义在 A 标签的后面,还是说必须定义在 A 标签的前面?

  • 虽然 Mybatis 解析 Xml 映射文件是按照顺序解析的,但是,被引用的 B 标签依然可以定义在任何地方,Mybatis 都可以正确识别。原理是,Mybatis 解析 A 标签,发现 A 标签引用了 B 标签,但是 B 标签尚未解析到,尚不存在,此时,Mybatis 会将 A 标签标记为未解析状态,然后继续解析余下的标签,包含 B 标签,待所有标签解析完毕,Mybatis 会重新解析那些被标记为未解析的标签,此时再解析 A 标签时,B 标签已经存在,A 标签也就可以正常解析完成了。

16.Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?

  • 不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。原因就是 namespace+id 是作为 Map<String, MappedStatement>的 key 使用的,如果没有namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。

17.Mybatis 都有哪些 Executor 执行器?它们之间的区别是什么?

  • Mybatis 有三种基本的 Executor 执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
    • 1)SimpleExecutor:每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。
    • 2)ReuseExecutor:执行 update 或 select,以 sql 作为key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map
    • 3)BatchExecutor:执行update(没有select,JDBC批处理不支持select) 将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

18.Mybatis 中如何指定使用哪一种 Executor 执行器?

  • 在 Mybatis 配置文件中,可以指定默认的 ExecutorType 执行器类型,也可以手动给DefaultSqlSessionFactory 的创建 SqlSession 的方法传递 ExecutorType 类型参数。

19.Mybatis 执行批量插入,能返回数据库主键列表吗?

  • 可以 使用 useGenerateKeys和keyProperty返回主键列表

20.在 mapper 中如何传递多个参数?

  • 封装一个实体类 或者直接传多个参数 使用 #{}来获取
  • 如果传参接收不到可以使用 @param 注解

21.resultType resultMap 的区别?

  • 类的名字和数据库相同时,可以直接设置 resultType 进行自动映射
  • 如果不相同则定义resultMap实现字段和实体类属性名称的匹配

22.使用 MyBatis 的 mapper 接口调用时有哪些要求?

  • Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同
  • Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同
  • Mapper 接口方法的返回值类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
  • Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径
  • 在使用foreach标签时如果有多个入参 则collection属性值为对应参数名称
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值