面试笔记@Mybatis

介绍一下 MyBatis

MyBatis 是一款优秀的持久层框架。

  • 支持自定义 SQL、存储过程以及高级映射
  • 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
  • 通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录

Mybaits 的优缺点

优点:

  • 消除 JDBC 中的重复代码
  • 可以在 XML 或注解中直接编写 SQL 语句,比较灵活,方便对 SQL 的优化与调整
  • SQL 写在 XML 中,与代码解耦,按照对应关系方便管理
  • XML 中提供了动态 SQL 的标签,方便根据条件拼接 SQL
  • 提供了 XML、注解与 Java 对象的映射机制
  • 与 Spring 集成比较方便

缺点:

  • 字段较多、关联表多时,编写 SQL 工作量较大
  • SQL 语句依赖了数据库特性,会导致程序的移植性较差,切换数据库困难

MyBatis主要执行流程

    1.  mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,

其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。

    2.  mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。

    3.  通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。

    4.  SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。

    5.  Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。

该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型。

更多细节详见:Mybatis之工作原理          MyBatis原理分析(通俗易懂)

MyBatis 与 Hibernate 的区别

  • MyBatis 不完全是一个 ORM 框架,它需要程序员自己编写 SQL;Hibernate 可以做到无 SQL 对数据库进行操作
  • MyBatis 直接编写原生 SQL,可以严格控制 SQL 执行性能,灵活度高,快速响应需求变化;Hibernate 会根据模型配置自动生成和执行 SQL 语句,面对多变的需求,灵活度没那么高
  • MyBatis 书写 SQL 可能依赖数据库特性,导致应用程序数据库一致性差;Hibernate 可以屏蔽掉数据库差异,数据库一致性好
  • MyBatis 考验程序编写 SQL 的功底,编写大量 SQL,效率可能不高;Hibernate 对象关系映射能力强,可以节省很多代码,提高开发效率
  • MyBatis 没法根据模型自动初始化数据库中的表;Hibernate 是根据模型的配置生成 DDL 语句在数据库中自动初始化对应表、索引、序列等

#{} 和 ${} 的区别

  • MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ?,预编译 SQL,通过 PreparedStatement 的 setXxxx 的方法进行参数赋值。使用 #{} 可以有效地防止 SQL 注入。
  • MyBatis 在处理 ${} 时,会直接把 ${} 替换为参数值,存在 SQL 注入的风险。
  • #{} 比 ${} 安全,但还是提供了 ${} 这种动态替换参数的方式,是因为有些复杂的 SQL 使用场景通过预编译的方式比较麻烦,且在代码中完全可以做到控制非法参数,有些参数可能是一些常量或字段值。

MyBatis 中实体类的属性名与表中的字段名不一致怎么处理?

1、修改 SQL,给查询字段重命名,如 将 user_id  重命名为 userId

select user_id as userId from table

2、MyBatis 的 XML 映射文件中,使用 <resultMap> 标签,定义数据库字段名与实体 bean 的属性字段名的映射关系

<select id="getUser" parameterType="int" resultMap="”UserMap”">
    select * from user where user_id=#{id}
</select>
 
<resultMap type=”User” id=”UserMap”>
    <!–- id 标签映射主键字段 -–>
    <id property=”id” column=user_id>

    <!–- result 标签映射非主键字段,property 为实体 bean 属性名,column 为数据库表中字段名 -–>
    <result property=“userName” column =”user_name”/>
</reslutMap>

MyBatis 中的本地缓存和二级缓存的作用是什么?怎么实现的?

本地缓存

作用:

SqlSession 级别的缓存,默认开启,在 MyBatis 配置文件中可以修改 MyBatis 文件中 <setting> 标签 localCacheScope 参数值改变缓存的作用域。statementId、boundSql.getSql() 执行 sql、查询参数、RowBounds 都相同,即认为是同一次查询,返回缓存值。
实现原理:

每个 SqlSession 对象包含一个 Executor 对象,Executor 对象中 localCache 属性使用 PerpetualCache 对象缓存查询数据;从源码中看 DefaultSqlSession 的 close、commit、rollback、insert、delete、update 相关的方法都会触发 BaseExecutor 对象清掉缓存。

二级缓存

作用:
MappedStatement 级别的缓存,默认不开启,可以在 Mapper xml 中通过 <cache> 标签开启 或者 MyBatis 文件中 <setting> 标签设置 cacheEnabled 参数为 true 全局开启 或者 mapper xml 配置文件中的 select 节点需要加上属性 useCache,在 SqlSession 关闭或提交之后才会生效。


开启二级缓存的默认作用摘自官网

  • 映射语句文件中的所有 select 语句的结果将会被缓存。

  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。

  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。

  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。

  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

实现原理:

  • XMLMappedBuilder 解析 Mapper xml 中的 <cache>、<cache-ref> 标签

  • 通过 builderAssistant 对象 addMappedStatement 方法,设置 cache 信息到 MappedStatement 对象内

  • CachingExecutor 对象的 query 方法先 MappedStatement 对象中 getCache() 获取缓存 Cache 对象,如果没有查到则到 BaseExecutor 中查询,走本地缓存逻辑

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值