Java面试题-day21 Mybatis

Mybatis

1. Mybatis架构或工作流程

Java面试题-day21 Mybatis

  1. mybatis配置
    SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环 境等信息。
    mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需 要在SqlMapConfig.xml中加载。
    2) 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
    3) 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
    4) mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
    5) Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
    6) Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
    7) Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

2. Mapper.xml中statement中属性含义

  1.  id:sql语句唯一标识
    
  2.  parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼		接在sql中。
    
  3. resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
  4. resultMap:resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系resultMap实质上还需要将查询结果映射到pojo对象中。
    resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象 中包括pojo和list实现一对一查询和一对多查询。
  5.  #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
    
  6.  ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进	行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
    

3. SqlSessionFactory

SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

4. SqlSession

SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

5. Mybatis中自主主键如何获取

#{}:如果传入的是pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属 性.属性… 如果要返回数据库自增主键:可以使用select LAST_INSERT_ID()
执行 select LAST_INSERT_ID()数据库函数,返回自增的主键 keyProperty:将返回 的主键放入传入参数的Id中保存.
order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后 执行是AFTER resultType:id的类型,也就是keyproperties中属性的类型

6. Mybatis中uuid主键如何获取

需要增加通过select uuid()得到uuid值
要将User中的id改成String类型,并且将User表中的id字段改为varchar(36)

7. Mapper接口开发方法

通常Mybatis开发Dao方法有两种。即原始Dao开发方法和Mapper接口开发方法。
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper接口开发需要遵循以下规范:

  1. Mapper.xml文件中的namespace与mapper接口的类路径相同。
  2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
  4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

8. selectOne和selectList

动态代理对象调用sqlSession.selectOne()sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

9. 动态sql

通过mybatis提供的各种标签方法实现动态拼接sql。

foreach标签:循环传入的集合参数
collection:传入的集合的变量名称
item:每次循环将循环出的数据放入这个变量中
open:循环开始拼接的字符串
close:循环结束拼接的字符串
separator:循环中拼接的分隔符
where标签作用:会自动向sql语句中添加where关键字,会去掉第一个条件的and关键字。
include标签:调用sql条件

10. Mybatis缓存机制

将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关 系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系 统的性能问题。
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。
mybaits提供一级缓存,和二级缓存。

Java面试题-day21 Mybatis
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在 对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession 之间的缓存数据区域(HashMap)是互相不影响的。
一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql 语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓 存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后 该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中 的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句, 多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以 共用二级缓存,二级缓存是跨SqlSession的。
二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不 同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同 即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内 存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis 默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。
如果缓存中有数据就不用从数据库中获取,大大提高系统性能。

二级缓存的应用场景
对查询频率高,变化频率低的数据建议使用二级缓存。
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用 mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较 高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓 存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60 分钟、24小时等,根据需求而定。

Mybatis缓存的局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信 息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品 信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商 品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper 为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此 类问题需要在业务层根据需求对数据有针对性缓存。

11. Mybatis实现分布式缓存

ehcache是一个分布式缓存框架。
EhCache 是一个纯Java的进程内缓存框架,是一种广泛使用的开源Java分布式缓 存,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
我们系统为了提高系统并发,性能、一般对系统进行分布式部署(集群部署方式)

Java面试题-day21 Mybatis
不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统开发。所以要使用 分布式缓存对缓存数据进行集中管理。
mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。

12. Mybatis逆向工程

使用官方网站的mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和 mapper映射文件。
作用:mybatis官方提供逆向工程,可以使用它通过数据库中的表来自动生成Mapper 接口和映射文件(单表增删改查)和Po类.

13. Mybatis解决jdbc编程的问题

  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
    解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
  2. Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
    解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
  3. 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
    解决:Mybatis自动将java对象映射至sql语句,通过statement中的 parameterType定义输入参数的类型。
  4. 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

14. Hibernate与Mybatis对比

首先简单介绍下两者的概念
Hibernate :Hibernate 是当前最流行的ORM框架,对数据库结构提供了较为完整 的封装。
Mybatis:Mybatis同样也是非常流行的ORM框架,主要着力点在于POJO 与SQL 之间的映射关系。

其次具体从几个方面说一下两者的区别:

1.两者最大的区别
针对简单逻辑,Hibernate和MyBatis都有相应的代码生成工具,可以生成简单基 本的DAO层方法。
针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有 良好的映射机制,开发者无需关心SQL生成与结果映射,可更专注于业务流程。
2.开发难度对比
Hibernate的开发难度要大于Mybatis。主要由于Hibernate比较复杂、庞大,学习 周期较长。
而Mybatis则相对简单一些,并且Mybatis主要依赖于sql的书写,让开发者感觉 更熟悉。
3.sql书写比较
Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。不过没有自己的 日志统计,所以要借助log4j来记录日志。
Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开 发的简洁性。不过Hibernate具有自己的日志统计。
4.数据库扩展性比较
Mybatis由于所有SQL都是依赖数据库书写的,所以扩展性,迁移性比较差。
Hibernate与数据库具体的关联都在XML中,所以HQL对具体是用什么数据库并不 是很关心。
5.缓存机制比较
相同点:Hibernate和Mybatis的二级缓存除了采用系统默认的缓存机制外,都可 以通过实现自己的缓存或为其他第三方缓存方案,创建适配器来覆盖缓存行为。
不同点:Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配 置,然后再在具体的表-对象映射中配置是那种缓存。
MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对 不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间*享相同的 缓存配置和实例,通过Cache-ref来实现。
两者比较:因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。 所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。
而MyBatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更 新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常 运行带来很大的隐患。

6.总结

Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成 SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事 务和SQL语句。

而MyBatis的优势是MyBatis可以进行更为细致的SQL优化,可以减少查询字段,并且容易掌握。

Hibernate的优势是DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。 数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。 有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

上一篇:爪哇(java)复习day21-2021/10/20


下一篇:Day21 static