问题: 请说一下mybatis 使用那些设计模式
建造者模式 (XmlConfigBuilder)在建造者模式中在使用建造者
单列模型 在mybatis 错误上下文使用 不是整个应用全局唯一 而是线程上全局唯一
在mybatis 配置类也使用了外观模式 装饰者模式也在mybatis 当中使用了 等等
问题 1:说说 Mybatis 与 Hibernate 的相同点和不同点
参考答案:
相同点
Hibernate 与 MyBatis 都是优秀 ORM 框架,都可以通过 XML 配置文件由 SessionFactoryBuider 生成 SessionFactory,然后由 SessionFactory 生成 Session,最后由 Session 来开启执行事务和 SQL 语句。
其中 SessionFactoryBuider,SessionFactory,Session 的生命周期都是差不多的。Hibernate 和 MyBatis 都支持 JDBC 和 JTA 事务处理。
不同点
(1)Hibernate 是全自动,而 MyBatis 是半自动
查询关联对象或者关联集合对象时,Hibernate 可以根据对象关系直接获取,自动生成 sql;而 MyBatis 仅有基本的字段映射,需要手动编写 sql 来完成。
(2)Hibernate 数据库耦合性比 MyBatis 要低很多
Hibernate 通过对象映射和 hql 语言,降低了语言与源数据库(Oracle、MySQL 等)的耦合性;而 MyBatis 由于需要手写 sql,因此与源数据库的耦合性很高,如果要移植到不同的数据库,又使用了某数据库特有的 sql 语法,还需要手动修改 sql,移值性比较差。
(3)Hibernate 的 SQL 灵活度和优化上比 MyBatis 要差很多
Hibernate 的 sql 很多都是自动生成的,无法直接维护 sql,而它的 hql 功能要比 sql 差不少,优化起来比较麻烦;而 MyBatis 的 sql 都是写在 xml 里,因此优化 sql 会方便很多。
(4)Hibernate 的缓存机制 MyBatis 不同
Hibernate 使用二级缓存时如果出现脏数据,系统会报错并提示;MyBatis 的二级缓存是在每个具体的表 - 对象映射中进行配置,这样针对不同的表可以自定义不同的缓存机制;而且 Mybatis 可以在命名空间中通过 Cache-ref 来共享相同的缓存配置和实例。
(5)Hibernate 的日志系统比 MyBatis 更好
Hibernate 日志系统非常健全,涉及广泛,包括:sql 记录、关系异常、优化警告、缓存提示、脏数据警告等;MyBatis 主要是基本的记录功能,要差很多。
点评:
这类题目在之前的专栏中已经出现过多次,不过在框架专题中再次出现,则要特别重视框架题的强实践性。换句话说,这类问题还可以换一种问法:
你们项目中使用提哪种 ORM 框架?为什么使用这种框架?相比其他框架的好处是什么?
可以看到,知其然还要知其所以然,这是这类强实践性问题的基本要求。要让面试官认为你是一个有追求有潜力的候选人,那么在项目中你就不能只是执行者,即使你干的是执行者的活,但你必须要有成为架构师的潜力,所以需要把项目中的上下游调用链路都搞清楚,把项目技术选型的背后逻辑也要搞清楚。
回到这道题本身,本质上就是技术造型,也就是说当时项目中为什么选择 MyBatits/Hibernate?
其实二者技术上最核心的区别就是自由度与灵活性,基于这点出发,带来二者一系列的不同,比如说耦合度、SQL 优化、上手难度等等,二者的不同点就可以基于此进行自由发挥;而二者的相同点也不必在缓存特性等一些技术细节上过多纠缠,不要限制得太死,这些异同点都可以结合自己项目中的示例来进行说明。
而项目中为什么选择某个框架,除了技术上的考量,更多的时候还要考虑项目的可维护性与学习成本等非技术原因,举个例子,如果团队之前一直使用 Hibernate,基于此已经有了一系列的配套工具包,而且团队成员对此都很熟悉,那么在技术相差不大的情况下很可能是继续使用 Hibernate。这些都是技术选择时需要考虑的因素。
问题 2:Mybatis DAO 接口为什么不需要实现类?
参考答案:
在启动加载配置文件时,Mybatis 会根据配置以 JDK 的动态代理方式去生成 Dao 的实现。即在 session.getMapper () 中使用了代理,每调用一次此方法,就会产生一个代理 class 的实例。
问题 3:Mybatis 中 #和 $ 的区别是什么?
参考答案:
# 和 $ 都是 Mybatis 的占位符。
(1) #变量在预编译阶段生效,此时会将 sql 中的 #替换为?号,调用 PreparedStatement 的 set 方法来赋值;而 $ 变量是在动态 SQL 解析阶段生效,直接进行字符串替换;
(2)# 方式能够很大程度防止 sql 注入,而 $ 方式无法防止 Sql 注入;