Mybatis面试总结

Mybatis面试总结

一、Mybatis的优缺点?

优点:

  • 基于sql编程,相当灵活,不会对应用程序或者数据库现有的设计造成任何影响,sql写在xml里面,解耦了sql和代码,便于维护和统一管理,提供了xml标签、支持编写动态sql语句,并可以重用。
  • 提供了标签映射,支持对象与数据库的ORM字段关系映射
  • 与JDBC相比消除了冗余代码,不需要手动开关连接
  • 很好的与各种数据库兼容,与Spring很好的集成

缺点:

  • sql语句编写工作量较大,对开发人员编写sql的功底有一定的要求。
  • sql语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

二、Mybatis和Hibernate对比?

  • 开发速度:
    • 如果项目中用到的复杂查询基本没有,就是简单的CRUD,这样选择Hibernate效率就很快,因为纯ORM框架基本的sql语句已经被封装好了,根本不需要去写sql,这样就节约了大量的时间,但是想对于一个大型项目,有复杂的业务场景(复杂的sql语句较多),选择Mybatis就会快很多,而且语句管理维护比较方便。
  • 开发工作量:
    • Mybatis和Hibernate都有相应的代码生成工具,可以生成简单的DAO层方法,针对高级复杂查询Mybatis需要手写sql,而Hibernate有良好的映射机制,开发者无需关心sql的生成与结果映射,可以更加专注于业务流程开发。
  • sql优化方面:
    • Hibernate的查询是会将所有的字段都查询出来,这一点会消耗性能,Hibernate也可以手动编写sql来指定查询字段,但是这样破坏了Hibernate开发的简洁性,Mybatis的sql是手动编写的,所以可以按需查询字段
  • 对象管理:
    • Hibernate是完整的ORM对象/关系映射解决方案,它提供了对象的状态管理功能(state
      management),使开发者不需要理会底层数据库细节。而Mybatis需要开发者对对象进行详细的管理
  • 缓存机制:
    • 都可以使用自己的缓存或者使用其他三方的缓存方案
    • Hibernate的二级缓存配置在sessionFactory生成的配置文件中进行配置,然后在具体的表-对象映射中配置是哪种缓存,Mybatis 二级缓存配置都是在每个具体的表-对象映射中进行配置,这样针对不同的表可以自定义不同的缓存机制。

当然SQL和ORM的争论永远不会停止。

三、#{}和${} 区别?

  • #{}是预编译是占位符,${} 是字符串替换、拼接
  • Mybatis在处理#{}时,会将sql中的#{} 替换为?号,调用ps来赋值
  • Mybatis在处理 时 , 会 将 s q l 中 的 {}时,会将sql中的 sql{} 替换为变量的值
  • #{} 替换后对应的变量字段加上单引号,${} 只是替换、拼接不会加上单引号
  • #{} 可以有效的防止sql注入,提供系统安全性

四、Mybatis 缓存

Mybatis 中有一级缓存和二级缓存:

  • 默认情况下一级缓存是开启的,而且是不能关闭的。一级缓存是指 SqlSession 级别的缓存,当在同一个 SqlSession 中进行相同的 SQL 语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存 1024 条 SQL。

    • 第一次发出一个查询 sql,sql 查询结果写入 sqlsession 的一级缓存中,缓存使用的数据结构是一个
      map(key:MapperID+offset+limit+Sql+所有的入参)

    • 同一个 sqlsession 再次发出相同的 sql,就从缓存中取出数据。如果两次中间出现 commit 操作(修改、添加、删除),本 sqlsession 中的一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。

  • 二级缓存是指可以跨 SqlSession 的缓存。是 mapper 级别的缓存,对于 mapper 级别的缓存不同的 sqlsession 是可以共享的。

    • 二级缓存的范围是 mapper 级别(mapper 同一个命名空间),mapper 以命名空间为单位创建缓存数据结构,结构是
      map(key:MapperID+offset+limit+Sql+所有的入参)。
    • mybatis 的二级缓存是通过 CacheExecutor 实现的。CacheExecutor其实是 Executor 的代理对象。所有的查询操作,在 CacheExecutor 中都会先匹配缓存中是否存在,不存在则查询数据库。
    • 具体使用需要配置:
      • Mybatis 全局配置中启用二级缓存配置
      • 在对应的 Mapper.xml 中配置 cache 节点
      • 在对应的 select 查询节点中添加 useCache=true

五、Mybatis插件的运行原理?如何编写一个插件

Mybatis只支持针对ParameterHander、ResultSetHander、StatementHander、Executor这4个接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法的拦截,每当执行这4个接口对象方法时候,就会进入代理对象的拦截方法,具体的就是InvocationHandler的 invoke()方法,拦截那些指定需要拦截的方法。

编写插件:实现Mybatis的interceptor接口并重写intercept()方法,然后在给插件编写注解,指定要拦截哪个接口的哪些方法即可,在配置文件中配置编写的插件。

六、说一下对Mybatis的连接池的理解

创建Connection过程如下:

  1. 初始化驱动: 判断driver驱动是否已经加载到内存中,如果还没有加载,则会动态地加载driver类,并实例化一个Driver对象,使用DriverManager.registerDriver()方法将其注册到内存中,以供后续使用。

  2. 创建Connection对象: 使用DriverManager.getConnection()方法创建连接。

  3. 配置Connection对象: 设置是否自动提交autoCommit和隔离级别isolationLevel。

  4. 返回Connection对象。

创建一个Connection对象代价是巨大的,耗时远远大于执行简单SQL的时间。

解决方案:

对于需要频繁地跟数据库交互的应用程序,可以在创建了Connection对象,并操作完数据库后,可以不释放掉资源,而是将它放到内存中,当下次需要操作数据库时,可以直接从内存中取出Connection对象,不需要再创建了,这样就极大地节省了创建Connection对象的资源消耗。由于内存也是有限和宝贵的,这又对我们对内存中的Connection对象怎么有效地维护提出了很高的要求。我们将在内存中存放Connection对象的容器称之为 连接池(Connection Pool)。

Connection对象的回收:

当我们的程序中使用完Connection对象时,如果不使用数据库连接池,我们一般会调用 connection.close()方法,关闭connection连接,释放资源。调用过close()方法的Connection对象所持有的资源会被全部释放掉,Connection对象也就不能再使用。如果使用了连接池,我们在用完了Connection对象时,需要将它放在连接池中,就要使用代理模式,为真正的Connection对象创建一个代理对象,代理对象所有的方法都是调用相应的真正Connection对象的方法实现。当代理对象执行close()方法时,要特殊处理,不调用真正Connection对象的close()方法,而是将Connection对象添加到连接池中

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值