目录
为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
Mybatis都有哪些Executor执行器?它们之间的区别是什么?
MyBatis是什么?
MyBatis是一个半自动的ORM(对象关系映射)持久层框架,支持定制化SQL。
为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
之所以说mybatis是半自动的,是因为mybatis需要手动写sql。Hibernate属于全自动的,因为配置java bean和数据表的映射关系后,可以直接使用hql进行数据库操作,不需要编写sql;不过hql并不是万能的,对于某些复杂的查询场景会非常麻烦。
传统JDBC开发存在的问题
- 频繁的创建销毁数据库连接对象,容易造成资源浪费。可以使用连接池,但是要自己实现连接池的相关代码。
- 在java代码中编写sql,sql变动要改变java代码,不方便。
- sql参数的设置、查询结果集的获取转换和资源的释放都十分繁琐,代码量大。
Mybatis是如何解决传统JDBC开发的问题的?
- 可以直接在mybatis的xml配置文件中配置数据库连接池,非常简单。
- mybatis的sql统一编写在xml配置文件中,修改sql不必改动java代码。
- mybatis可以传递多种类型去作为sql参数,同时对于查询结果集也能映射到多种数据类型(集合、bean等)。
Hibernate 和 MyBatis 的区别
- mybatis是一个半自动的ORM框架,开发人员必须自己编写sql;hibernate是一个全自动ORM框架,通过配置Java对象与数据库表的关系,能够做到不用编写sql就能操作数据库。
- mybatis的数据库移植性比hibernate要差,因为mybatis是手写sql,如果写开发人员没有这方面的经验容易产生这类问题;hibernate通过bean表映射和hql能忽略掉数据库sql的具体细节,由hibernate根据不同数据库生成sql,直接操作数据库,所以移植性好。
- 不过也正是因为hibernate的sql可以直接生成,所以在复杂场景下对sql的优化比较麻烦;而mybatis因为是手写sql,所以优化分方便。
#{}和${}的区别
#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。预编译就是传入的参数只会被当成值,因为会为参数加上单引号;而${}不会加单引号,参数可能会称为sql语句的一部分。
Mybatis中的缓存机制
https://www.cnblogs.com/wuzhenzhao/p/11103043.html
mybatis中有一、二级缓存,默认一级缓存是开启的,开启二级缓存需要进行配置。mybatis查询数据的顺序是:二级缓存——>一级缓存——>数据库。
一级缓存
- 作用域:一级缓存的作用域是SqlSession,也就是数据库会话。项目中通常会创建多个SqlSession,它们之间是相互独立的,这意味着内部的缓存数据也是相互独立的。
- 数据结构:SqlSession类有一个Executor属性,这个属性中维护了一个PerpetualCache对象,里面有一个HashMap,这个HashMap就是用来存储一级缓存数据的。
- 缓存更新机制:当执行select语句时,会将查询结果存储在当前会话的一级缓存中;当执行更新操作(insert、update、delete)时,为了保证当前会话中缓存的一致性,当前会话中的缓存会失效。
- 生命周期:一级缓存的生命周期是数据库会话的生命周期,当会话结束后,一级缓存也失效了。
- 问题:若项目中存在多个会话,当一个会话在数据库中修改了另一个会话中缓存的数据,另一个会话就有可能读到脏数据。解决:mybatis一级缓存有两种:session和statement。可以把缓存模式改成statement(配置文件中配置),这样每次查询结束时会清理掉一级缓存(BaseExecutor的query方法)。
二级缓存
- 作用域:二级缓存主要是为了解决一级缓存不能跨会话共享的问题,作用域是namespace,也就是一个mapper内的所有方法共享一份缓存,而所有mapper缓存对所有的会话都是共享的。
- 数据结构或实现:SqlSession使用CachingExecutor执行sql语句,CachingExecutor是对普通Executor的装饰,查询时会先从会话外部指定的namespace缓存中进行查找,有就返回,没有就委托被装饰的Executor(执行器)进行查找,会先查找一级缓存,有就返回,没有就查询数据库,然后把数据添加到一级和二级缓存中。
- 缓存更新机制:缓存添加和失效的机制和一级缓存一致。
- 生命周期:和整个应用的生命周期一致。
- 问题:跨namespace也可能会出现数据脏读的问题。解决:1.多个namespace共享一个缓存(如下)。2.关闭二级缓存。
<cache-ref namespace="其它命名空间" />
Mybatis都有哪些Executor执行器?它们之间的区别是什么?
- SimpleExecutor:每次执行update或select操作,都会创建一个Statement对象,用完立刻关闭。
- ReuseExecutor:每次执行update或select操作,会先根据sql(key)查找有没有已经创建好的statement,有就使用,没有就创建,创建之后会放到map中,以便下次使用。
- BatchExecutor:执行update时,可以缓存多个Statement,然后一起执行。
- CachingExecutor :开启二级缓存后使用的查询器,是对以上三种执行器的装饰。查询时,会现在二级缓存中查询,没有再使用普通查询器进行查询。