MyBatis核心面试题
MyBatis优点(为什么用MyBatis 不用jpa)
MyBatis提供了连接池(避免了打开连接池 关闭连接池带来的代码的冗余) 提供了缓存的功能,自动结果的封装
提供了动态SQL语句能力,将SQL语句和java代码分离 提供了高级映射规则
MyBatis运行的流程/原理: mybatis提供的两个配置文件config主配置文件和mapper配置文件,通过配置文件可以得到SqlSessionFactory 工厂对象 通过SqlSessionFactory工厂对象可以得到sqlSession 得到session后可以执行SQL。
SqlSession通过底层提供的Exexutor执行器执行SQL语句,mybatis 将mapper.xml中的sqlStatement 解析为MappedStatement对象 通过参数输入 参数类型有三种 HashMap 简单类型 pojo
在数据库中执行SQL语句 输出得到结果 输出类型有三种 HashMap,简单类型 pojo
mybatis的输入参数类型: 简单类型 pojo hashmap
mybatis任何解决实体类的属性和数据库列名不一致的情况: 在查询SQL语句的时候给列名起个别名 手动映射resultmap 将结果封装成hashmap 驼峰命名规则
mybatis 进行取值的时候 可以使用$ 和# 二者的区别是什么?
#取值的时候是对SQL语句进行一个预编译 用占位符?来代替 用于参数传递 $ 是对SQL语句的and拼接
#{}:预编译占位符 SQL语句用?号代替
#{}:获取参数时和参数名无关
#{}:可以防止SQL注入${} 不能防止SQL注入
${}SQL语句的拼接 需要判断参数的类型 做具体的处理
${} 获取参数通过${value} 如果指定参数名需要通过@param("xxx") 在接口的方法声明中指定。
mybatis基于接口方式对数据库进行操作的时候 需要遵循哪些规则:
1) Mapper 的namespace必须和mapper接口的全路径一致
2) Mapper接口的方法名必须和SQL定义的id一致
3) Mapper接口中方法的输入参数类型必须和SQL定义的parameterType 一致
4) Mapper接口中方法是输出参数类型必须和SQL定义的resultType 一致
mybatis是任何支持多环境配置的? 在config配置文件里面 标签<environments> 有两个属性 default 属性用来选择某一个环境是生效的 id属性是用来指定现在用的是哪一个环境 一个<environments> 标签是一个配置环境。
当接口中的参数有多个时 你是如何取值的? 将这些参数封装成对象 或者封装成hashmap 可以使用#{0} #{1}.... 或者#{param1} #{param2} 或者在方法的参数前面加注解 @param
mybatis 常用的动态SQL语句的标签有哪些? if choose-when-otherwise foreach(批量删除) set(可以有选择性的修改) where(模糊查询) trim
if choose-when-otherwise 的区别: if 是做条件的一个and拼接 可能有条件 可以没有条件 可能有多个条件 choose-when-otherwise 最多最少都会只执行一个条件 哪个在前面并且满足条件就先执行它
mybatis的查询策略(mybatis是怎么做查询的?):mybatis在做查询的时候 不是直接去数据库查询的 而是先去缓存中命中(查询) 如果命中成功则直接将结果返回 没有命中 此时会先去数据库中查询 将查询到的结果存储一份到缓存中 然后再将结果返回 当下一次做相同查询的时候 就可以直接从缓存中命中 当做增删改的时候 会刷出缓存。
mybatis对缓存的支持: 提供了一级缓存和二级缓存 一级缓存的作用域是session默认是开启的 当openSession() 后 如果执行相同的SQL(相同语句和参数) 不执行SQL语句 而是从缓存中命中返回 所以手动关闭。二级缓存的作用域是一个mapper的namespace 同一个namespace中查询SQL语句可以从缓存中命中 二级缓存是可以跨session的 也是自动开启的 但是我们还是要手动开启 虽然它默认是开启的 但是要指明二级缓存的开关 但是如果我们不手动开启的话 是没有效果的。此外还需要在核心配置文件的setting中配置cacheEnabled 同时pojo对象必须是可序列化的 既要求实现序列化接口。
如何开启缓存: 开启二级缓存 在mapper.xml 文件中加入<cache/>
使用时注意事项: 必须要让你的实体类实现序列化接口 所以二级缓存 它的本质是实现序列化的过程,二级缓存不需要我们手动关闭。
当返回的结果中包含了另外一个对象的引用时 需要我们手动映射 通过association 高级映射 把你的结果映射到结果集里面
当返回的结果包含了一个集合的引用时, 通过collection高级映射 来把你的结果映射到集合里面。
连接池原理: 没有缓冲区的话 每次的访问都要去访问数据库 每次的访问都会造成数据库的压力 所以我们要创建一个缓冲区 每次查询的时候就到缓冲区中获取连接 当查询完毕之后 再把连接归还到缓冲区中
常见的缓存淘汰机制有哪些? 缓存满了如何去清理: 一共就两种 1: 先进先出 按照时间去排序 最先到缓冲区的会最先出去 它可以保证缓存里面的都是最新的热点。2: 最小活跃度
接口中的方法是不能重载(同类同名不同参)的 因为mapper.xml 里面的SQL语句的id是唯一的
ORM:对象关系映射