当前位置: 首页 > 后端技术 > Java

三天彻底的mybatis面试千篇一律的文章

时间:2023-04-02 00:50:22 Java

本文已收录在Github仓库,内容包括计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模型、架构、校招社招分享等核心知识点,欢迎star~Github地址:https://github.com/Tyson0314/Java-learning什么是Mybatis?MyBatis框架是一个开源的数据持久层框架。它在内部封装了通过JDBC访问数据库的操作,支持常见的SQL查询、存储过程和高级映射,几乎免去了所有手动设置JDBC代码和参数以及检索结果集的工作。MyBatis作为持久层框架,其主要思想是将程序中大量的SQL语句剥离出来,配置在配置文件中,实现SQL的灵活配置。这样做的好处是SQL与程序代码分离,无需修改代码,直接在配置文件中修改SQL即可。什么是ORMORM(ObjectRelationalMapping),对象关系映射,是一种解决关系数据库数据与简单Java对象(PO??JO)之间映射关系的技术。简单的说,ORM通过描述对象与数据库映射关系的元数据,自动将程序中的对象持久化到关系型数据库中。Mybatis和Hibernate的区别?主要有以下区别:Hibernate的开发难度比MyBatis大,主要是因为Hibernate更复杂,体积更大,学习周期更长。Hibernate是一个全自动的ORM映射工具。使用Hibernate查询关联对象或关联集合对象时,可以根据对象关系模型直接获取,因此是全自动的。Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,因此被称为半自动ORM映射工具。数据库可扩展性的差异。Hibernate和数据库的具体关系是在XML中的,所以HQL并不是很关心具体使用的是什么数据库。MyBatis的可扩展性和迁移性很差,因为所有的sql都写在数据库里。缓存机制的差异。Hibernate的二级缓存配置在SessionFactory生成的配置文件中详细配置,然后在具体的表对象映射中配置那种缓存。MyBatis的二级缓存配置在每个具体的表对象映射中进行详细的配置,这样可以针对不同的表定制不同的缓存机制,MyBatis可以在namespace中共享相同的缓存配置和实例,通过Cache-ref来达到。日志系统完整性的差异。Hibernate的日志系统非常完善,涉及面也很广,而Mybatis除了基本的记录功能外,还有很多薄弱的功能。在sql优化方面,Mybatis比Hibernate方便多了。由于Mybatissql是用xml写的,优化sql比Hibernate方便多了。但是Hibernate的很多SQL都是自动生成的,不能直接维护;总之,Hibernate在写SQL方面不如Mybatis灵活。MyBatis框架优缺点及适用场合与JDBC相比,代码量减少50%以上。MyBatis是一个简单易学的持久层框架,小巧易学。MyBatis非常灵活,不会对应用程序或数据库的现有设计造成任何影响。SQL写在XML文件中,与程序代码完全分离,降低耦合,便于统一管理和优化,可复用。提供XML标签,支持编写动态SQL,满足不同业务需求。提供映射标签,支持对象和数据库之间的ORM字段关系映射。缺点编写SQL语句的工作量比较大,对开发人员编写SQL的能力有一定的要求。SQL语句依赖于数据库,所以数据库的可移植性不好,不能随便更换数据库。适用场景MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。对于性能要求高或者需求变化比较大的项目,比如Web项目,MyBatis是最好的选择。Mybatis工作原理阅读MyBatis配置文件:mybatis-config.xml是MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,比如数据库连接信息。加载地图文件。映射文件即SQL映射文件,配置了操作数据库的SQL语句,需要加载到MyBatis配置文件mybatis-config.xml中。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。构造会话工厂:通过MyBatis环境等配置信息构造会话工厂SqlSessionFactory。创建会话对象:SqlSession对象是由会话工厂创建的,它包含了执行SQL语句的所有方法。Executor:MyBatis底层定义了一个Executor接口来操作数据库。它会根据SqlSession传递的参数动态生成要执行的SQL语句,并负责维护查询缓存。MappedStatement对象:在Executor接口的execution方法中,有一个MappedStatement类型的参数,封装了映射信息,用于存放要映射的SQL语句的id、参数等信息。入参映射:入参类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC为preparedStatement对象设置参数的过程。输出结果映射:输出结果类型可以是Map、List等集合类型,也可以是基本数据类型、POJO类型。输出结果映射过程类似于结果集的JDBC解析过程。Mybatis有哪些Executors?它们之间有什么区别?Mybatis有3个基本的Executor,SimpleExecutor、ReuseExecutor和BatchExecutor。SimpleExecutor:每次执行update或select时,打开一个Statement对象,用完Statement对象立即关闭。ReuseExecutor:执行update或select,以sql为key查找Statement对象,存在则使用,不存在则创建。使用完后,Statement对象不会关闭,而是放在Map中,供下次使用。简而言之,Statement对象被重用。BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql加入批处理(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement之后object是addBatch(),它等待执行executeBatch()批处理一个一个。与JDBC批处理相同。作用范围:Executor的这些特性被严格限制在SqlSession生命周期的范围内。在MyBatis中实现接口绑定有几种方式?通过注解绑定,在接口方法上添加@Select@Update等注解与Sql语句绑定(当SQL语句比较简单时,推荐使用注解绑定)通过WriteSQLinxml进行绑定,并指定在xml映射文件必须是接口的全路径名(当SQL语句比较复杂时,推荐使用xml绑定)。Mybatis是如何进行分页的?Mybatis使用RowBounds对象进行分页,对ResultSet结果集是内存分页,而不是物理分页。先把所有的数据都查出来,然后再做分页。可以在sql中直接写带物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。分页插件背后的基本原理是什么?分页插件的基本原理是利用Mybatis提供的插件接口实现一个自定义的插件,在插件的拦截方法中拦截要执行的sql,然后重写sql(SQLsplicinglimit),并根据dialectdialect和物理分页参数添加相应的物理分页语句,使用技术JDK动态代理,使用责任链设计模式。简述Mybatis插件的运行原理。Mybatis只能为ParameterHandler、ResultSetHandler、StatementHandler、Executor这四个接口编写插件。Mybatis利用JDK的动态代理,为需要拦截的接口生成代理对象,实现接口方法拦截功能。当执行到这四个接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法。当然,只有你指定要拦截的那些方法才会被拦截。.如何写一个插件?写一个插件:实现Mybatis的Interceptor接口并重写intercept()方法,然后给插件写注解,指定拦截哪个接口的哪些方法,最后在配置里配置你写的插件文件。.Mybatis支持延迟加载吗?Mybatis只支持关联对象和集合对象的延迟加载。关联是指一对一查询,集合是指一对多查询。在Mybatis的配置文件中,可以配置是否开启懒加载lazyLoadingEnabled=true|false。延迟加载背后的基本原理是什么?懒加载的基本原理是利用CGLIB创建目标对象的代理对象,当目标方法被调用时,进入拦截器方法。例如调用a.getB().getName()时,拦截器invoke()方法发现a.getB()为null值,则单独发送与B对象关联的预先保存的sql查询,查询B,然后调用a.setB(b),使得a的对象b属性有值,然后完成a.getB().getName()方法的调用。当然,不仅仅是Mybatis,包括Hibernate在内的几乎所有的都支持懒加载的原理是一样的。{}和${}有什么区别?{}解析成预编译语句,预编译后直接执行,无需重新编译sql。//sqlMap中的以下sql语句select*fromuserwherename=#{name};//解析成预编译语句;编译SQL语句然后取值select*fromuserwherename=?;${}isonlyforoneStringreplacement每次执行sql前都需要编译,存在sql注入问题。select*fromuserwherename='${name}'//当传入的参数为“ruhua”时,解析如下,然后发送到数据库服务器进行编译。取值后编译SQL语句。select*fromuserwherename="ruhua";Mybatis预编译数据库收到sql语句后,需要进行词法语义分析,对sql语句进行优化,制定执行计划。这需要一些时间。如果一个sql语句需要重复执行,每次都进行语法检查和优化会浪费很多时间。预编译语句是将sql语句中的值替换为占位符,即模板化sql语句。一次编译多次运行,无需解析优化。mybatis是通过PreparedStatement和placeholders预编译的。mybatis底层使用PreparedStatement。默认情况下,所有的sql都会被预编译,#{}会被替换成?,然后是带占位符的sql模板?将发送到mysql服务器。编译后缓存编译结果,然后直接执行真正参数的sql。预编译的作用:预编译阶段可以优化sql的执行。大多数情况下可以直接执行预编译的sql,数据库服务器不需要重新编译,可以提高性能。准备好的语句对象可以重用。缓存一个sql预编译后生成的PreparedStatement对象,下次同样的sql,可以直接使用这个缓存的PreparedState对象。防止SQL注入。使用预编译,后面注入的参数不会被SQL编译。也就是说后面注入的参数系统不会认为是SQL语句,而是默认是参数。##一级缓存和二级缓存缓存:合理使用缓存是优化中最常用的方法之一。将从数据库中查询到的数据放入缓存中。下次使用时,不需要从数据库中查询,直接从缓存中读取,避免频繁操作数据库,减轻数据库压力,同时提高系统性能。一级缓存是SqlSession级缓存:Mybatis支持缓存。默认只开启一级缓存,一级缓存的作用域是同一个SqlSession。在SQL和参数相同的情况下,我们使用同一个SqlSession对象调用同一个Mapper方法,往往只执行一次SQL。因为第一次使用SqlSession查询后,Mybatis会将结果放在缓存中。后面再查询的时候,如果没有需要刷新的语句,缓存也没有超时,SqlSession只会取出当前缓存的数据,不会重试向数据库发送SQL。如果使用不同的SqlSession,因为不同的SqlSession之间是相互隔离的,所以不会使用一级缓存。二级缓存是mapper级缓存:缓存可以在SqlSession之间共享。默认不开启二级缓存,需要在mybatis-config.xml中开启二级缓存:并在对应的Mapper.xml文件中添加缓存标签,表示启用哪个mapper缓存:二级缓存要求返回的POJO必须可序列化,即需要实现Serializable接口。启用二级缓存后,数据查询执行流程为二级缓存->一级缓存->数据库。最后给大家分享一个Github仓库,里面有大斌编译的300多本经典计算机书籍PDF,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构还有算法,机器学习,编程生活等等,可以star一下,下次找书的时候可以直接在上面搜索,仓库持续更新中~Github地址:https://github.com/Tyson0314/java-books