• JAVA面试八股文----Mybatis


    1、Mybatis

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

    Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
    Mybatis在处理 0 时,就是把 0时,就是把 0时,就是把{}替换成变量的值。

    有了#{}为什么还需要${}?

    #{}会被预编译处理,可以有效的防止SQL注入,提高系统安全性。
    对于需要动态构建SQL的场景 , 比如条件查询,${}可以用来拼接SQL片段 , 构建动态的表名、列名等。

    1.2 Mybatis和ORM(Object Relation Mapping hibernate(jpa)区别

    mybatis和hibernate都同处于持久层的框架。
    mybatis是粗粒度的封装
    hibernate是细粒度的封装
    Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBG,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程,直接编写原生态sql
    Hibernate对象/关系映射能力强,让使用者直接面向对象编程,不用关心sql

    1.3 Mybatis怎么封装动态SQL(常见的动态sql的标签)

    Mybatis提供了9种动态sql标签: where | set foreach | if | choose| when | otherwise|trim

    1.4 Mybatis怎么实现分页 (利用插件pagehelper)

    分页插件原理:使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sqI,然后重写sql,添加对应的物理分页语句和物理分页参数

    1.5 插件原理

    在MyBatis中插件是通过拦截器来实现的,那么既然是通过拦截器来实现的,就会有一个问题,哪些对象才允许被拦截呢?
    四大对象:Executor , StatementHandler,ParameterHandler,ResultSetHandler
    Mybatis只能针对上面的四大对象进行拦截
    上面4个创建好之后并没有直接返回,而是都调用executor = interceptorChain.pluginAll(executor);
    将上面4个对象都放到pluginAll 做了一个处理,又返回了一个该对象
    里面用了对原对象进行的动态代理,代理的时候,加入了拦截器的执行
    但是并不是这四大对象中的所有方法都能被拦截,下面就是官网提供的可拦截的对象和方法汇总:

    在这里插入图片描述

    1.6 Mybatis使用了哪些设计模式?

    建造者: SqlSessionFactoryBuiler、XMLConfigBuiler
    工厂: SqlSessionFactor
    **代理:**MappedProxy使用的是jdk的动态代理
    模板方法: BaseExcutor和SimpleExecutor

    1.7 Mybatis如何实现主键回填?

    方式一:useGeneratedKeys

    <insert id="adduser" parameterType="com.gxa.entity.user"
    useGeneratedKeys=true" keyProperty="id"">
    INSERT INTO t_user(user_name , pwd)
    VALUES(#{username] ,#{pwd})
    </insert>
    

    方式二:selectKey标签实现主键返回

    <insert id="adduser2" parameterType="com. gxa.entity.user" >
    <!-- selectKey标签实现主键返回 -->
    <!-- keyproperty:主键对应的pojo中的哪一个属性
    <!-- order(设置在执行insert语句前执行查询id的sq1,还是在执行insert语句之后执行查询id的sq1 -->
    <!-- resultTypes设置返回的id的类型-->
    <selectKey keyProperty="id" order="AFTER" resu1tType="int">
               SELECT LAST_INSERT_ID(
    </selectKey>
    INSER INTo t_user(user_name , pwd)  VALUES(#{username},#{pwd})
    </inse
    

    1.8 Mybatis一级缓存和二级缓存有什么区别?

    1)一级缓存是SqlSession级别的缓存,底层使用map集合实现,当Session flush或close之后,该Session中的所有Cache就将清空,默认打开。
    2)二级缓存是SqlSessionFactory级别的缓存,不同的SqlSession可以共享。默认不打开,要开启使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),在它的映射文件中配置;
    **3)**对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了C/U/D操作后,默认该作用域下所有select中的缓存将被clear。
    查询的顺序是:
    先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
    如果二级缓存没有命中,再查询一级缓存
    如果一级缓存也没有命中,则查询数据库
    SqlSession关闭之前,一级缓存中的数据会写入二级缓存

    1.9 mybatis的实现原理?【源码】

    (1)读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。
    (2)加载映射文件。就是SQL映射文件,文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载,可以加载多个映射文件,每个文件对应数据库中的一张表
    (3)构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory.
    (4)创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法
    (5) Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqISession传递的参数动态地生成需要执行的SQL语句,同时维护查询缓存。
    (6) MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
    (7)输入参数映射。JDBC对preparedStatement对象设置参数的过程。
    (8)输出结果映射。JDBC对结果集的解析过程。
    都可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。

    mybatis源码上的体现:

    1、根据配置文件(全局,sql映射)初始化出Configuration对象
    2、创建1DefaultSqlSession对象,里面包含Configuration以及Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
    3、DefaultSqlSession.getMapper ():拿到Mapper接口对应的MapperProxy;
    4、MapperProxy里面有(DefaultSqlSessioh) ;
    5、执行增删改查方法:
    1)、调用DefaultSqlSession的增删改查(Executor) ;
    2)、会创建StatementHandler对象。同时创建出ParameterHandler和ResultSetHandler
    3)、调用StatementHandler预编译参数以及设置参数值;使用ParameterHandler来给sql设置参数
    4)、调用StatementHandler的增删改查方法;
    5)、ResultSetHandler封装结果

    1.10 通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

    Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:
    com,mybatis3.mappers.StudentDao.findStudentByld,可以唯一找到namespace为
    com.mybati3.mappers.StudentDao下面id = findStudentByld的MappedStatement。在Mybatis中,每一个标签,都会被解析为一个MappedStatement对象。Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
    Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

    1.11 如何执行批量插入?

    方式一:foreach
    方式二:批量插入,在java代码中打开sqlSession的时候指定: ExecutorType.BATCH

    经过测试,foreach的性能很好,甚至比batch好

    1.12 MyBatis实现一对一映射,一对多映射

    一对一: association

    一对多:collection

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

    Mybatis仅支持association(一对一)关联对象和collection(一对多)关联集合对象的延迟加载,在Mybatis配置文件中置是否启用延迟加载
    lazyLoadingEnabled=true | false,默认是关闭的,使用的时候再发送sql去进行查询。

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

  • 相关阅读:
    每日一题:AJAX进度监控(附可运行源码)
    不知道10年老电脑如何重装系统?其实很简单
    STM32(垃圾桶开关盖)
    面试官:去重和幂等的理解掌握多少?
    什么是http无状态?怎么解决的?
    HTML静态网页成品作业(HTML+CSS)——电影网首页网页设计制作(1个页面)
    前端每日小计
    沉睡者IT - 什么是Web3.0?
    jeecgboot-前端组件封装代码示例
    灵途科技荣获省级“专精特新”企业认定!
  • 原文地址:https://blog.csdn.net/weixin_64646820/article/details/139474466