源码
BaseJdbcLogger
打印日志的抽象类。
PreparedStatementLogger
PreparedStatement
的日志。
ResultSetLogger
ResultSet
的日志。
打印debug的日志
1 | protected void debug(String text, boolean input) { |
字符串前缀
1 | private String prefix(boolean isInput) { |
打印日志的抽象类。
PreparedStatement
的日志。
ResultSet
的日志。
1 | protected void debug(String text, boolean input) { |
1 | private String prefix(boolean isInput) { |
1 | package org.denger.mapper; |
1 | <?xml version="1.0" encoding="UTF-8"?> |
1 | package org.denger.mapper; |
对于以上极其简单代码看上去并无特殊之处,主要亮点在于 UserMapper
居然不用实现类,而且在调用 getUser
的时候,也是使用直接调用了UserMapper
实现类,那么Mybatis是如何去实现 UserMapper
的接口的呢?
可能你马上能想到的实现机制就是通过动态代理方式,看看MyBatis整个的代理过程吧。
首先在Spring的配置文件中看到下面的Bean。1
2
3
4<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<property name="basePackage" value="org.denger.mapper"></property>
</bean>
1 | /** |
以上的MapperScannerConfigurer
的注释中描述道。
从base包中搜索所有下面所有interface
,并将其注册到Spring Bean容器中,其注册的class bean是MapperFactoryBean
。
看看它的注册过程,从MapperScannerConfigurer#Scanner
类中抽取,在初始化以上application-content.xml
文件时就会进行调用。
主要用于是搜索base packages
下的所有mapper.class
,并将其注册至spring的benfinitionHolder
中。
一级缓存,又叫本地缓存,是PerpetualCache
类型的永久缓存,保存在执行器中(BaseExecutor
),而执行器又在SqlSession
(DefaultSqlSession
)中,所以一级缓存的生命周期与SqlSession
是相同的。
MyBatis的一级缓存指的是在一个Session
域内,Session
为关闭的时候执行的查询会根据SQL为key
被缓存,单独使用MyBatis而不继承Spring,使用原生的MyBatis的SqlSessionFactory
来构造sqlSession
查询,是可以使用以及缓存的。
当参数不变的时候只进行一次查询,参数变更以后,则需要重新进行查询,而清空缓存以后,参数相同的查询过的SQL也需要重新查询,当执行SQL时两次查询中间发生增删改操作,则SqlSession
的缓存清空。
如果集成Spring是没有使用一级缓存。原因是一个sqlSession,但是实际上因为我们的dao继承SqlSessionDaoSupport
,而SqlSessionDaoSupport
内部sqlSession
的实现是使用用动态代理实现的,这个动态代理sqlSessionProxy
使用一个模板方法封装select()
等操作,每一次select()
查询都会自动先执行openSession()
,执行完后调用close()
方法,相当于生成一个新的session
实例,所以我们无需手动的去关闭这个session()
,当然也无法使用MyBatis的一级缓存,也就是说MyBatis的一级缓存在Spring中是没有作用的。
MyBatis SqlSession provides you with specific methods to handle transactions programmatically. But when using MyBatis-Spring your beans will be injected with a Spring managed SqlSession or a Spring managed mapper. That means that Spring will always handle your transactions.
You cannot call SqlSession.commit(), SqlSession.rollback() or SqlSession.close() over a Spring managed SqlSession. If you try to do so, a UnsupportedOperationException exception will be thrown. Note these methods are not exposed in injected mapper classes.
二级缓存,又叫自定义缓存,实现Cache
接口的类都可以作为二级缓存,所以可配置如encache等的第三方缓存。二级缓存以namespace
名称空间为其唯一标识,被保存在Configuration
核心配置对象中。1
2
3
4
5public class Configuration {
// ...
protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
// ...
}
每次构建SqlSessionFactory
对象时都会创建新的Configuration
对象,因此,二级缓存的生命周期与SqlSessionFactory
是相同的。在创建每个MapperedStatement
对象时,都会根据其所属的namespace
名称空间,给其分配Cache
缓存对象。
二级缓存同样执行增删查改操作,会清空缓存。
二级缓存就是global caching
,它超出session
范围之外,可以被所有sqlSession
共享,它的实现机制和MySQL的缓存一样,开启它只需要在MyBatis的配置文件开启settings
里。
Update your browser to view this website correctly. Update my browser now