MyBatis 缓存

MyBatis 缓存

MyBatis缓存分为顶级缓存和二级缓存

一流缓存

MyBatis的一流缓存指的是在一个Session域内,session为关闭的时候实施的查询会遵照SQL为key被缓存(跟mysql缓存一样,修改任何参数的值都会促成缓存失效)

1)单独拔取MyBatis而不连续Spring,使用原生的MyBatis的SqlSessionFactory来布局sqlSession查询,是可以动用以及缓存的,示例代码如下

图片 1

public class Test {
    public static void main(String[] args) throws IOException {
        String config = "mybatis-config.xml";
        InputStream is = Resources.getResourceAsStream(config);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        System.out.println(session.selectOne("selectUserByID", 1));
        // 同一个session的相同sql查询,将会使用一级缓存 
        System.out.println(session.selectOne("selectUserByID", 1));
        // 参数改变,需要重新查询
        System.out.println(session.selectOne("selectUserByID", 2));
        // 清空缓存后需要重新查询
        session.clearCache();
        System.out.println(session.selectOne("selectUserByID", 1));
        // session close以后,仍然使用同一个db connection
        session.close();
        session = factory.openSession();
        System.out.println(session.selectOne("selectUserByID", 1));
    }
}

图片 2

输出如下

DEBUG – Openning JDBC Connection
DEBUG – Created connection 10044878.
DEBUG – ooo Using Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ? 
DEBUG – ==> Parameters: 1(Integer)
1|test1|19|beijing
1|test1|19|beijing
DEBUG – ooo Using Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ? 
DEBUG – ==> Parameters: 2(Integer)
2|test2|18|guangzhou
DEBUG – ooo Using Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ? 
DEBUG – ==> Parameters: 1(Integer)
1|test1|19|beijing
DEBUG – Resetting autocommit to true on JDBC Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – Closing JDBC Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – Returned connection 10044878 to pool.
DEBUG – Openning JDBC Connection
DEBUG – Checked out connection 10044878 from pool.
DEBUG – Setting autocommit to false on JDBC Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – ooo Using Connection
[com.mysql.jdbc.JDBC4Connection@9945ce]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ? 
DEBUG – ==> Parameters: 1(Integer)
1|test1|19|beijing

看以看出来,当参数不变的时候只进行了一回询问,参数变更将来,则需要再行举办查询,而清空缓存将来,参数相同的询问过的SQL也亟需重新查询,而且动用的数据库连接是同一个数据库连接,这里要得益于大家在mybatis-config.xml里面的datasource设置

图片 3

<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">

            </transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>

图片 4

留神datasource使用的是POOLED,也就是拔取了连接池,所以数据库连接可回收利用,当然那一个environment属性在集成spring的时候是不需要的,因为我们需要此外配置datasource的bean.

 

2) 跟Spring集成的时候(使用mybatis-spring)

平昔在dao里查询两遍同样参数的sql

图片 5

@Repository
public class UserDao extends SqlSessionDaoSupport {
    public User selectUserById(int id) {
        SqlSession session = getSqlSession();
        session.selectOne("dao.userdao.selectUserByID", id);
        // 由于session的实现是SqlSessionTemplate的动态代理实现
        // 它已经在代理类内执行了session.close(),所以无需手动关闭session
        return session.selectOne("dao.userdao.selectUserByID", id);
    }
}

图片 6

观望日志

DEBUG – Creating a new SqlSession
DEBUG – SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@1e389b8] was
not registered for synchronization because synchronization is not
active
DEBUG – Fetching JDBC Connection from DataSource
DEBUG – JDBC Connection
[jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8,
UserName=root@localhost, MySQL-AB JDBC Driver] will not be managed by
Spring
DEBUG – ooo Using Connection
[jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8,
UserName=root@localhost, MySQL-AB JDBC Driver]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ?
DEBUG – ==> Parameters: 1(Integer)
DEBUG – Closing non transactional SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@1e389b8]
DEBUG – Returning JDBC Connection to DataSource
DEBUG – Creating a new SqlSession
DEBUG – SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@169da74] was
not registered for synchronization because synchronization is not
active
DEBUG – Fetching JDBC Connection from DataSource
DEBUG – JDBC Connection
[jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8,
UserName=root@localhost, MySQL-AB JDBC Driver] will not be managed by
Spring
DEBUG – ooo Using Connection
[jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8,
UserName=root@localhost, MySQL-AB JDBC Driver]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ?
DEBUG – ==> Parameters: 1(Integer)
DEBUG – Closing non transactional SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@169da74]
DEBUG – Returning JDBC Connection to DataSource

 

那里举行了2次sql查询,看似我们利用了同一个sqlSession,不过实际上因为我们的dao继承了SqlSessionDaoSupport,而SqlSessionDaoSupport内部sqlSession的落实是运用用动态代理实现的,这多少个动态代理sqlSessionProxy使用一个模板方法封装了select()等操作,每五回select()查询都会自动先举行openSession(),执行完close()未来调用close()方法,相当于生成了一个新的session实例,所以咱俩无需手动的去关闭这一个session()(关于那点见下面mybatis的官方文档),当然也无力回天选取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,
UnsupportedOperationException exception will be thrown. Note these
methods are not exposed in injected mapper classes.

 

二级缓存

二级缓存就是global
caching,它不止session范围之外,可以被抱有sqlSession共享,它的落实机制和mysql的缓存一样,开启它只需要在mybatis的布局文件开启settings里的

<setting name="cacheEnabled" value="true"/>

以及在对应的Mapper文件(例如userMapper.xml)里打开

图片 7

<mapper namespace="dao.userdao">
   ...  select statement ...
       <!-- Cache 配置 -->
    <cache
        eviction="FIFO"
        flushInterval="60000"
        size="512"
        readOnly="true" />
</mapper>

图片 8

内需小心的是global
caching的功效域是针对Mapper的Namespace而言的,也就是说只在有在那个Namespace内的查询才能共享这一个cache.例如地点的
dao.userdao namespace, 下面是合法文档的牵线

It’s important to remember that a cache configuration and the cache
instance are bound to the namespace of the SQL Map file. Thus, all
statements in the same namespace as the cache are bound by it.

譬如说下面的示范,我们举行三遍对同一个sql语句的询问,观察输出日志

图片 9

    @RequestMapping("/getUser")
    public String getUser(Model model) {
        User user = userDao.selectUserById(1);
        model.addAttribute(user);
        return "index";
    }

图片 10

当我们走访五遍 /getUser 这多少个url,查看日志输出

DEBUG – Creating a new SqlSession
DEBUG – SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@659812] was
not registered for synchronization because synchronization is not
active
DEBUG – Cache Hit Ratio [dao.userdao]: 0.0
DEBUG – Fetching JDBC Connection from DataSource
DEBUG – JDBC Connection
[jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8,
UserName=root@localhost, MySQL-AB JDBC Driver] will not be managed by
Spring
DEBUG – ooo Using Connection
[jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8,
UserName=root@localhost, MySQL-AB JDBC Driver]
DEBUG – ==> Preparing: SELECT * FROM user WHERE id = ? 
DEBUG – ==> Parameters: 1(Integer)
DEBUG – Closing non transactional SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@659812]
DEBUG – Returning JDBC Connection to DataSource
DEBUG – Invoking afterPropertiesSet() on bean with name ‘index’
DEBUG – Rendering view
[org.springframework.web.servlet.view.JstlView: name ‘index’; URL
[/index.jsp]] in DispatcherServlet with name ‘dispatcher’
DEBUG – Added model object
‘org.springframework.validation.BindingResult.user’ of type
[org.springframework.validation.BeanPropertyBindingResult] to
request in view with name ‘index’
DEBUG – Added model object ‘user’ of type [bean.User] to request in
view with name ‘index’
DEBUG – Forwarding to resource [/index.jsp] in InternalResourceView
‘index’
DEBUG – Successfully completed request
DEBUG – Returning cached instance of singleton bean
‘sqlSessionFactory’
DEBUG – DispatcherServlet with name ‘dispatcher’ processing GET
request for [/user/getUser]
DEBUG – Looking up handler method for path /user/getUser
DEBUG – Returning handler method [public java.lang.String
controller.UserController.getUser(org.springframework.ui.Model)]
DEBUG – Returning cached instance of singleton bean ‘userController’
DEBUG – Last-Modified value for [/user/getUser] is: -1
DEBUG – Creating a new SqlSession
DEBUG – SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@539a92] was
not registered for synchronization because synchronization is not
active
DEBUG – Cache Hit Ratio [dao.userdao]: 0.5
DEBUG – Closing non transactional SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@539a92]
DEBUG – Rendering view
[org.springframework.web.servlet.view.JstlView: name ‘index’; URL
[/index.jsp]] in DispatcherServlet with name ‘dispatcher’
DEBUG – Added model object
‘org.springframework.validation.BindingResult.user’ of type
[org.springframework.validation.BeanPropertyBindingResult] to
request in view with name ‘index’
DEBUG – Added model object ‘user’ of type [bean.User] to request in
view with name ‘index’
DEBUG – Forwarding to resource [/index.jsp] in InternalResourceView
‘index’
DEBUG – Successfully completed request

可以见见第二次访问同一个url的时候同样的查询 hit cache了,这就是global
cache的效应

The End

网站地图xml地图