Configuration
Mybatis将配置文件信息和映射文件信息解析封装到Configuration对象里,该对象是Mybatis的核心类,但是Mybatis并没有提供Configuration对象的方法。
每个xml标签都有它对应的封装类
事务对象
Mybatis使用JdbcTransactionFactory和ManagedTransactionFactory两个工厂类来生产Transaction对象,JdbcTransaction提供自动提交事务,提交事务,和回退事务的方法,在关闭连接之前,会将事务设置为自动提交。,而ManagedTransaction虽然也提供了提交和回滚事务方法,但是是个空实现。根据Mybatis-config.xml的配置closeConnection属性为false时,可ManagedTransaction的关闭连接方法失效,默认是true。
DataSource
Mybatis提供JndiDataSourceFactory,UnpooledDataSourceFactory,PooledDataSourceFactory三个工厂,JndiDataSourceFactory用于整合第三方的数据源,如Tomcat,weblogic。UploadedDataSource是 无连接池数据源,每次获取请求都简单的打开和关闭连接。
PooledDataSource
PooledDataSource是一个简单,同步,线程安全数据库连接池的数据源,PooledDataSource提供了一系列的连接池配置,每个配置都会导致连接池的所有连接全部强转关闭,关闭时,如果其连接的不是自动提交的,会进行回滚。连接池里面的连接PooledConnection其实是个Connection的代理类,拦截了Connection的Close方法,当代用Close方法时,会根据当前连接状态来决定放入空闲链表中还是释放掉。并对Connection的其他方法都进行监听,优先检查连接是否有效,无效会抛出SQLException异常。
可以设置poolPingEnabled属性启动ping机制检查连接,设置poolPingConnectionsNotUsedFor属性确定ping检测时间间隔,通常用于检测超时连接(默认为0,即当开启检测后每次从连接词中获取连接以及放回连接池都需要检测),设置poolPingQuery属性检查连接正确的语句,默认为"NO PING QUERY SET",即没有,使用会导致抛异常
缓存
Mybatis缓存回收策略类都是基于装饰者设计模式进行开发的。策略类之间是可以互相委托,一般委托类是PerpetualCache(永久缓存 Cache接口实现类,里面就是维护着一个HashMap,这是 Cache接口唯一一个基础实现,其他实现类全都是装饰模式持有另一个缓存策略对象)。
默认是开启二级缓存缓存,只需要在Mapper上配置
这个简单语句的效果如下:
映射语句文件中的所有 select 语句的结果将会被缓存。
映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
缓存不会定时进行刷新(也就是说,没有刷新间隔)。
缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
下面是更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突
可用的清除策略有:
LRU – 最近最少使用:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。
flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。
size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。
注意事项
由于在更新时会刷新缓存, 因此需要注意使用场合:查询频率很高, 更新频率很低时使用, 即经常使用 select, 相对较少使用delete, insert, update。
缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。但刷新缓存是刷新整个 namespace 的缓存, 也就是你 update 了一个, 则整个缓存都刷新了。
最好在 「只有单表操作」 的表的 namespace 使用缓存, 而且对该表的操作都在这个 namespace 中。 否则可能会出现数据不一致的情况。
TypHandler
MyBatis 中的 TypeHandler 类型处理器用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值。MyBatis 内置了大部分基本类型的类型处理器,所以对于基本类型可以直接处理,当我们需要处理其他类型的时候就需要自定义类型处理器。
LanguageDriver
Mybatis处理解析动态SQL的类,默认是语言驱动是XMLLanguageDriver 。XMLLanguager会根据SQL是否是动态SQL来决定用哪个SqlSource实例来进行解析。
像动态SQL,会使用DynamicSqlSource进行解析.DynamicSqlSource使用各动态SQL标签对应的SqlNode进行对应功能的解析,并将每个sqlNode的解析结果放到DynamicContext中,最终将封装到一个BoundSql对象中,BoundSql封装着参数映射,和可执行SQL脚本。
SqlSession
SqlSession提供select/insert/update/delete方法,在旧版本中使用使用SqlSession接口的这些方法,但是新版的Mybatis中就会建议使用Mapper接口的方法。
映射器其实就是一个动态代理对象,进入到MapperMethod的execute方法就能简单找到SqlSession的删除、更新、查询、选择方法,从底层实现来说:通过动态代理技术,让接口跑起来,之后采用命令模式,最后还是采用了SqlSession的接口方法(getMapper()方法等到Mapper)执行SQL查询(也就是说Mapper接口方法的实现底层还是采用SqlSession接口方法实现的)【MapperProxy】。
1)Execute:调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句;
2)StatementHandler:使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement;
3)ParammeterHandler:处理SQL参数;
4)ResultHandler:结果集ResultSet封装处理返回
KeyGenerator
Jdbc3KeyGenerator 主要用于数据库的自增主键,比如 MySQL、PostgreSQL;会将执行SQL后从Statemenet中获取主键放到参数对象对应的属性里
SelectKeyGenerator用于执行selectKey标签的SQL,将结果赋值到参数对象对应的属性中
NoKeyGenerator什么事情都不干,里面是空实现方法
Interceptor
实现Interceptor除了在Mybatis-config.xml上配置上去之外,还要将Interceptor的plugin方法加上 Plugin.wrap(target, this);才能执行到Interceptor的intercept方法。Plugin.wrap会实现target的代理类,监听Interceptor注解上的指定方法,当调用那些指定方法,代理类就会先去执行Interceptor的intercept方法.