这里是参考B站上的大佬做的面试题笔记。大家也可以去看视频讲解!!!
文章目录
- 1、mybatis和hibernate的对比
- 2 、#{}和${}的区别
- 3 、mybatis插件运行原理及开发流程
- 4 、索引的基本原理
- 5 、mysql聚簇和非聚簇索引的区别
1、mybatis和hibernate的对比
面向对象
SQL和ORM的争论,永远都不会终止
开发速度的对比:
- Hibernate的真正掌握要比Mybatis难些。Mybatis框架相对简单容易上手,但也相对简陋些。
比起两者的开发速度,不仅仅要考虑到两者的特性及性能,更要根据项目需求去考虑究竟哪一个更适合项目开发,比如:一个项目中用到的复杂查询基本没有,就是简单的增删改查,这样选择Hibernate
效率就很快了,因为基本的sql语句已经被封装好了,根本不需要你去写sql语句,这就节省了大量的时间,但是对于一个大型项目,复杂语句较多,这样再去选择Hibernate就不是一个太好的选择,选择mybatis就会加快许多,而且语句的管理也比较方便。
开发工作量的对比:
- Hibernate和Mybatis都有相应的代码生成工具。可以生成简单的DAO方法。针对高级查询,Mybatis需要手动编写sql语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心sql的生成与结果映射,可以更加专注于业务流程。
sql优化方面:
- Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。而Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。
Hibernate HQL语句的调优需要将SQL打印出来,而Hibernate的SQL被很多人嫌弃因为太丑了。Mybatis的sql是自己手动写的所以调整方便。但Hibernate具有自己的日志系统。mybatis本身不带日志系统,使用log4进行日志记录。
对象管理的对比
- Hibernate是完整的对象/关系映射解决方案,它提供了对象状态管理(state management)的功能,使开发者不再需要理会底层数据库系统的细节。也就是说,相对于常见的JDBC/SQL持久层方案中需要管理SQL语句,Hibernate采用了更自然的面向对象的视角来持久化java应用中的数据。
换句话说,使用Hibernate的开发者应该总是关注对象的状态(state),不必考虑SQL语句的执行。这部分细节已经由Hibernate掌管妥当,只有当开发者在进行系统性能调优的时候才需要进行了解。而Mybatis在这一块没有文档说明,用户需要对对象自己进行详细的管理。
缓存机制对比:
- 相同点:都可以实现自己的缓存或使用其他第三方缓存方案,创建适配器来完全覆盖缓存行为。
- 不同点:Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再具体的表-对象映射中配置是哪种缓存。
Mybatis的二级缓存配置都是在每个具体的表–对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。
两者比较:因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL,所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。
而mybatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。
Hibernate功能强大,数据库无关性好,O/R映射能力强,如果你对Hibernate相当精通,而且对Hibernate进行了适当的封装,那么你的整个项目持久性代码会相当简单,需要写的代码少,开发速度很快,很爽。
Hibernate的缺点就是学习门槛不低,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate方面需要你的经验和能力都很强才行。
IBATIS入门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很好的SQL使用经验,对于没有那么高的对象模型要求的项目来说,相当完美。
IBATIS的缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
2 、#{}和${}的区别
#{}
是预编译处理、是占位符,${}
是字符串替换,是拼接符- Mybatis在处理
#{}
时,会将sql中的#{}
替换为?,调用PrepareStatement
来赋值; - Mybatis在处理
${}
时,就是把${}
替换成变量的值,调用Statement
来赋值 {}的变量替换是在DBMS中,变量替换后,#{}对应的变量自动加上单引号
${}
的变量替换是在DBMS外,变量替换后,${}对应的变量不会加上单引号
- 使用#{}可以有校的防止SQL注入,提高系统安全性。
3 、mybatis插件运行原理及开发流程
Mybatis只支持针对ParameterHandler
、ResultSetHandler
、StatementHandler
、Executor
这四种接口的插件,Mybatis使用JDK的动态代理,为i需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这四种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,拦截那些你指定需要拦截的方法。
编写插件:实现Mybatis的interceptor接口并复写Intercept()
方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,在配置文件中配置编写的插件
4 、索引的基本原理
索引用来快速地寻找那些具有特定值的记录。如果没有索引,一般来说执行查询时遍历整张表。
索引的原理:就是把无序的数据变成有序的查询。
- 1 、把创建了索引的列内容进行排序
- 2 、对排序结果生成倒排表
- 3 、在倒排表内容上拼上数据地址链
- 4 、在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据。
5 、mysql聚簇和非聚簇索引的区别
都是B+树的数据结构
- 聚簇索引:将数据存储与索引放到了一块、并且是按照一定的顺序组织的、找到了索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。
- 非聚簇索引:叶子节点不存储数据、存储的是数据行地址,也就是说根据索引查到数据行的位置再取磁盘查找数据,这个就有点类似一本书的目录,比如我们要找第三章第一节,那我们先在这个目录里找,找到对应的页码后再去对应的页码查看文章。
优势:
- 1 、查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询(非覆盖索引的情况下)效率要高
- 2 、聚簇索引对于范围查询的效率很高,因为其数据是按照大小排列的
- 3 、聚簇索引适合用在排序的场合,非聚簇索引不适合
劣势:
- 1 、维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(page split)的时候。建议在大量插入新行后,选在负载较低的时间段,通过OPTIMIZE TABLE优化表,因为必须被移动的数据可能造成碎片。使用独享表空间可以弱化碎片。
- 2 、表因为使用UUID(随机ID)作为主键,使数据存储稀疏,这就会出现聚簇索引有可能有比全表扫更慢,所以建议使用int的auto_increment作为主键
- 3、如果主键比较大的话,那辅助索引将会变得更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用更多的物理空间。
innoDB中一定有主键,主键一定是聚簇索引,不手动设置、则会使用unique索引,没有unique索引,则会使用数据库内部的一个行的隐藏id来当作主键索引。在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是二次查找,非聚簇索引都是辅助索引,想复合索引、前缀索引、唯一索引、辅助索引叶子节点存储的不再是行的物理位置、而是主键值。
MyISM使用的是非聚簇索引,没有聚簇索引,非聚簇索引的两颗B+树上看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。
如果设计到大数据量的排序,全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的