Java面试——MyBatis相关知识

目录

1.什么是MyBatis

2.MyBatis优缺点

3.MyBatis工作原理

4.MyBatis缓存模式

5.MyBatis代码相关问题

6.MyBatis和hibernate区别


1.什么是MyBatis

MyBatis是一个半ORM持久层框架(对象关系映射),基于JDBC进行封装,使得开发者可以专注于SQL语句,不用关系JDBC操作的流程。

MyBatis支持定制化 、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOS(Plain Ordinary Java Object,普通的 Java对象,即实际开发中的实体类)映射成数据库中的记录。

2.MyBatis优缺点

MyBatis作为市面上应用最为广泛的数据库框架,具有以下优点:

  • 简单易学:本身就很小且简单。易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

  • 灵活便捷:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。同时,减少了JDBC相关代码,大大减少了代码量。

  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

  • 兼容性好:基于JDBC进行封装,所以可以和很多数据库兼容。

  • 提供xml标签,支持编写动态sql。

但同时,MyBatis也还具有一定的缺点:

  • SQL语句编程量较大,较为考验使用者的SQL功力。
  • SQL语句与具体数据库依赖很大,使得数据库移植性差。

3.MyBatis工作原理

MyBatis的工作原理主要依赖于SqlSessionFactory和SqlSession两大类。其主要分为两大过程:

(1)MyBatis启动加载。Mybatis会获取一个SqlSessionFactory对象,完成全局配置文件和映射文件的加载解析操作,然后把相关信息保存到Configuration对象中。然后通过SqlSessionFactory获取SqlSession对象(基于DefaultSqlSessio对象实现)。

SqlSessionFactory类,它是单个数据库映射关系经过编译后的内存镜像,主要是创建DefaultSqlSessionFactory对象进行具体实现。而SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来获得,而SqlSessionFactoryBuildr则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。

(2)MyBatis处理请求。SqlSession类中提供了处理请求的方法(select、update等),并调用对应的Executor处理。处理过程中,如果有配置缓存,先走二级缓存,再走一级缓存,缓存不命中,再走数据库操作。会通过StatementHandler处理,先通过ParameterHandler处理SQL中的占位符,再通过ResultSetHandler处理结果集的映射。

SqlSession类,同理,主要是创建DefaultSqlSession对象进行具体实现。SqlSession接口实例执行方法的过程中主要会去执行Executor类的方法,进行请求的具体处理。

总结来说,具体的工作流程就是通过SqlSessionFactoryBuilder从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例,再由SqlSessionFactory创建出一个SqlSession,并由该SqlSession进行请求的处理,执行事务和SQL语句。

4.MyBatis缓存模式

mybatis为减轻数据库压力,提高数据库性能,提供了两级缓存机制:

(1)一级缓存:

基于会话(session)的缓存。一级缓存是默认放开的,但需开启事务进行使用(就是同一个事务中的第二次查询会走缓存)。MyBatis中一级缓存也叫做本地缓存,于SqlSession层面实现的,所以作用范围是在同一个SqlSession中,不同的SqlSession及时查询相同的数据也不会走缓存。

(2)二级缓存:

基于进程(使用装饰器维护,涉及到了装饰器模式,需要了解可参考java设计模式——装饰器模式)的缓存。MyBatis中二级缓存的作用域是namespace(命名空间),所以很显然二级缓存是需要存储在SqlSession之外的:

二级缓存缓存范围比一级缓存更大,不同的SQLSession可以访问二级缓存的内容,所以二级缓存需要自己开启,哪些数据放入二级缓存需要自己指定。

开启方式(application.yml文件配置):

# mybatis相关配置
mybatis:
  configuration:
      #开启MyBatis的二级缓存
      cache-enabled: true

或是在mapper.xml文件中添加代码:

 其中eviction属性指缓存回收策略,flushInterval则是缓存更新时间(上述代码中为1分钟)

eviction:缓存的回收策略,默认的是 LRU。

  • LRU - 最近最少使用,移除最长时间不被使用的对象。
  •     FIFO - 先进先出,按对象进入缓存的顺序来移除它们。
  •     SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象。
  •     WEAK - 弱引用,更积极地移除基于垃圾收集器和弱引用规则的对象。
     

(3)三级缓存:

三级缓存又称为自定义缓存,如使用Redis进行缓存等,需要自行进行配置操作。

实际代码中如何开启

5.MyBatis代码相关问题

(1)获取自增主键:如果数据库中设计了主键id自动增长,那么可以通过MyBatis中的mapper.xml文件中的属性配置,获取该值,并进行插入:

<insert id="addEmployee" parameterType="employee" useGeneratedKeys="true" keyProperty="id">
    insert into tbl_employee (id, name, email, gender)
    values (#{id}, #{name}, #{email}, #{gender});
</insert>

核心代码为: useGeneratedKeys="true" keyProperty="id"

(2)属性名和字段名不一致:主要通过resultMap标签处理。

<resultMap id="empResultMap" type="Emp">
    <id column="student_id" property="id"></id>
	<result column="s_name" property="name"></result>    
</resultMap>
<select resultMap="empResultMap">
    select * from student where student_id = #{id}
</select>

(3)#和$的区别:

  • #{}是预编译处理,会把传入的数据都当成一个字符串来处理,所以会在传入的数据上面加一个双引号。其在mybatis处理时替换为?,然后进行赋值。
  • ${}是在mybatis处理时直接替换,作用相等于是字符串拼接,所以会有SQL注入风险。

例子:

select * from student where name= #{name}

上述语句中,该sql语句会将#{name}替换为?,然后获取到传入的@Param的参数值时(比如name="seven"),再传入(整个"seven"进行传入)。

select * from student where name= ${name}

 如果传入的name类型为整型类型,那么在执行sql语句时就不会出错,但是如果传入的name类型为字符串型,就会变成select * from student where name=seven,执行会报错。

所以,一般情况下,传入参数使用 #{},如果需要凭借SQL语句时,才使用${}。

6.MyBatis和hibernate区别

Hibernate也是一个对象关系映射框架,同样基于JDBC进行封装,工作原理与MyBatis类似。其余MyBatis之间主要区别如下:

MyBatis Hibernate
半自动框架,需要手动编写SQL语句 全自动的orm框架,hibernate可以自动生成SQL语句,自动执行
日志模块只有基本记录功能 拥有完成的日志系统
缓存模块需要在每个表-对象进行详细配置 缓存机制上更优
移植性较差 移植性更强
由于sql都是手动编写,且存于xml文件中,优化更为便捷

由于sql都是自动生成,优化较为困难,且遇到一些较为复杂的sql操作时,无法达成目的。

总结来说,mybatis较为轻便简单,而直接使用sql语句,开发更方便,上手更快。Hibernate框架更为复杂,也更加严谨。

猜你喜欢

转载自blog.csdn.net/tang_seven/article/details/128977837