1、mybatis源码分析面试
1.mybatis功能架构sql
2. SQL调用过程(mybatis工做原理)数据库
mybatis经过配置文件建立sqlsessionFactory,sqlsessionFactory根据配置文件,配置文件来源于两个方面:一个是xml,一个是Java中的注解,获取sqlSession。SQLSession包含了执行sql语句的全部方法,能够经过SQLSession直接运行映射的sql语句,完成对数据的增删改查和事物的提交工做,用完以后关闭SQLSession。 缓存
3. mybatis的SqlSessionFactory 与 SqlSession.安全
(1)首先,SqlSessionFactoryBuilder去读取mybatis的配置文件,而后build一个DefaultSqlSessionFactory。session
(2)当咱们获取到SqlSessionFactory以后,就能够经过SqlSessionFactory去获取SqlSession对象。mybatis
4. 利器之MapperProxy:架构
在mybatis中,经过MapperProxy动态代理我们的dao(mapper), 也就是说, 当我们执行本身写的dao里面的方法的时候,实际上是对应的mapperProxy在代理。app
(1)经过SqlSession从Configuration中获取。框架
(2)SqlSession把包袱甩给了Configuration, 接下来就看看Configuration。
(3)Configuration不要这烫手的山芋,接着甩给了MapperRegistry, 那咱看看MapperRegistry。
(4)MapperRegistry经过调用newInstance动态代理咱们写的dao接口。
5.Excutor
6.mybatis的缓存
6.1 一级缓存的做用域是SqlSession
Executor接口的实现类是由Configuration构造的:
public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor, autoCommit);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
最后咱们发现若是cacheEnabled这个属性为true的话,那么executor会被包一层装饰器,这个装饰器是CachingExecutor。其中cacheEnabled这个属性是mybatis总配置文件中settings节点中cacheEnabled子节点的值,默认就是true,也就是说咱们在mybatis总配置文件中不配cacheEnabled的话,它也是默认为打开的。
CachingExecutor执行sql的时候到底作了什么?
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();//这儿执行的是二级缓存
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, parameterObject, boundSql);
if (!dirty) {
cache.getReadWriteLock().readLock().lock();
try {
@SuppressWarnings("unchecked")
List<E> cachedList = (List<E>) cache.getObject(key);
if (cachedList != null) return cachedList;
} finally {
cache.getReadWriteLock().readLock().unlock();
}
}
List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
return list;
}
}
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
因为咱们没有开启二级缓存(二级缓存的内容下面会分析),所以这里执行了最后一句话。因此一级缓存最重要的代码就是BaseExecutor的query方法! 这个localCache就是一级缓存!
接下来咱们看下为什么执行新增或更新或删除操做,一级缓存就会被清除这个问题。
CachingExecutor的update方法
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);//这清除的是二级缓存
return delegate.update(ms, parameterObject);
}
BaseExecutor的update方法:
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) throw new ExecutorException("Executor was closed.");
clearLocalCache();
return doUpdate(ms, parameter);
}
6.2 二级缓存
二级缓存的做用域是全局,换句话说,二级缓存已经脱离SqlSession的控制了。二级缓存的做用域是全局的,二级缓存在SqlSession关闭或提交以后才会生效。
本文就说下最简单的配置,在mapper文件上加上这句配置便可:<
cache
/>
2、面试相关
1.mybatis是什么?
mybatis是一个优秀的持久层框架,他对jdbc操做数据库的过程进行了封装,使开发着只用关注sql自己,不用去关注例如注册驱动,加载连接,获得statement,处理结果集等复杂的过程。
mybatis经过xml或者注解的方式,将要执行的各类sql语句配置起来,并经过Java对象和statement中的sql语句映射生成最终的sql语句,最后由mybatis框架执行sql语句,并将结果映射成Java对象返回。
2.mybatis解决的问题
3. #{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。 Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值; Mybatis在处理${}时,就是把${}替换成变量的值。 使用#{}能够有效的防止SQL注入,提升系统安全性。
4.Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,能够在sql内直接书写带有物理分页的参数来完成物理分页功能,也可使用分页插件来完成物理分页。 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,而后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
5.什么是延迟加载
延迟加载的实例:
若是查询订单而且关联查询用户信息。若是先查询订单信息便可知足要求,当咱们须要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。
二者相同点
Hibernate与 MyBatis均可以是经过SessionFactoryBuider由XML配置文件生成SessionFactory,而后由 SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中 SessionFactoryBuider,SessionFactory,Session的生命周期都是差很少的。
Hibernate和MyBatis都支持JDBC和JTA事务处理。
Mybatis优点
MyBatis能够进行更为细致的SQL优化,能够减小查询字段。
MyBatis容易掌握,而Hibernate门槛较高。
Hibernate优点
Hibernate的DAO层开发比MyBatis简单,Mybatis须要维护SQL和结果映射。
Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
Hibernate数据库移植性很好,MyBatis的数据库移植性很差,不一样的数据库须要写不一样SQL。
Hibernate有更好的二级缓存机制。Hibernate缓存分为:
一级缓存:session共享(save、update、saveOrupdate、load、get、list) 用于处理当前的单元操做.
二级缓存:sessionFactory共享.(常常读不多被修改,若是使用二级缓存能够提升性能.)
MyBatis自己提供的缓存机制不佳。MyBatis 包含一个很是强大的查询缓存特性,它能够很是方便地配置和定制。默认状况下是没有开启缓存的,除了局部 的 session 缓存,能够加强变现并且处理循环依赖也是必须的。要开启二级缓存,你须要在你的 SQL 映射文件中添加一行: <cache/>
hibernate中session打开和关闭由sessionFactory的getSession()来管理session的打开和关闭。
第三方缓存实现:cache、Map等;