mybatis的缓存机制是怎么样的?
1.緩存,其存儲作用域為 Session,當 Session flush 或 close 之后,該Session中的所有 Cache 就將清空。
2. 二級緩存與一級緩存其機制相同,默認也是采用 PerpetualCache,HashMap存儲,不同在于其存儲作用域為 Mapper(Namespace),并且可自定義存儲源,如 Ehcache。
3. 對于緩存數據更新機制,當某一個作用域(一級緩存Session/二級緩存Namespaces)的進行了 C/U/D 操作后,默認該作用域下所有 select 中的緩存將被clear。
mybatis的一級緩存作用就是在同一個session過程中,將會對相同數據的存取不通過數據庫,而是通過緩存機制提高效率,看測試代碼
<img src="https://pic3.zhimg.com/50/c225e22b0d00f5903b3626009228767e_hd.jpg" data-rawwidth="307" data-rawheight="347" class="content_image" width="307"> import java.io.IOException; import java.io.InputStream;import junit.framework.TestCase;import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import com.guowuxin.mybatis.mapper.UserMapper; import com.guowuxin.mybatis.model.User;/*用戶表 drop table if exists user; create table user(id int primary key auto_increment,username varchar(50) unique,password varchar(100),useraddress varchar(50) ); insert into user values(1,"guowuxin","guowuxin","beijing"); insert into user values(1,"guoxiaoming","guowuxin","beijing"); *///如果兩次查詢都是查詢1 將只會發送一條sql語句到數據庫,否則將是2條sql語句public class TestClass extends TestCase{public static SqlSessionFactory sqlSessionFactoy;static{String resource = "mybatis-config.xml";try {InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactoy = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}@Test public void testgetUserById() { SqlSession sqlSession = sqlSessionFactoy.openSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); User u1=mapper.getUserById(1);System.out.println(u1);User u2=mapper.getUserById(1);System.out.println(u2);sqlSession.commit();} finally { sqlSession.close(); } } } package com.guowuxin.mybatis.mapper;import com.guowuxin.mybatis.model.User;//通過面向接口的mybatis編程方式,需要保證方法名和配置文件中的id名稱一致 public interface UserMapper {public User getUserById(int id); } package com.guowuxin.mybatis.model;public class User {private int id;private int age;private String userName;private String userAddress;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getUserAddress() {return userAddress;}public void setUserAddress(String userAddress) {this.userAddress = userAddress;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString(){final StringBuilder builder = new StringBuilder();builder.append("id=").append(id).append(",");builder.append("age=").append(age).append(",");builder.append("userName=").append(userName).append(",");builder.append("userAddress=").append(userAddress).append(".");return builder.toString();} } log4j.rootLogger=DEBUG,Console ?? #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d %t %-5p (%c) - %m%nlog4j.logger.com.ibatis=DEBUG log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><typeAliases><typeAlias alias="User" type="com.guowuxin.mybatis.model.User" /></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC" /><dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://127.0.0.1:3306/guowuxin" /><property name="username" value="root" /><property name="password" value="admin" /></dataSource></environment></environments><mappers><mapper resource="UserMapper.xml" /></mappers></configuration> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 這里namespace必須是PostsMapper接口的路徑,不然要運行的時候要報錯 “is not known to the MapperRegistry”--> <mapper namespace="com.guowuxin.mybatis.mapper.UserMapper"> <!-- 這兒的resultType是配置在mybatis-config.xml中得別名 --><select id="getUserById" parameterType="int" resultType="User">select * from user where id=#{id}</select> </mapper>
結果:
.................... 2016-02-24 20:12:37,568 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:37,568 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=? 2016-02-24 20:12:37,586 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer) id=1,age=0,userName=guowuxin,userAddress=beijing. id=1,age=0,userName=guowuxin,userAddress=beijing. 2016-02-24 20:12:37,593 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:37,593 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:37,593 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 3874052 to pool.
如果取得2個不同的id
....................... 2016-02-24 20:12:57,655 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 3874052. 2016-02-24 20:12:57,656 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:57,656 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=? 2016-02-24 20:12:57,664 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer) id=1,age=0,userName=guowuxin,userAddress=beijing. 2016-02-24 20:12:57,679 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:57,679 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=? 2016-02-24 20:12:57,679 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 2(Integer) id=2,age=0,userName=guoxiaoming,userAddress=beijing. 2016-02-24 20:12:57,679 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:57,679 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04] 2016-02-24 20:12:57,679 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 3874052 to pool.
二級緩存機制指的則是在不同的session之間都可以共享相同的數據內容。
import java.io.IOException; import java.io.InputStream;import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import com.guowuxin.mybatis.mapper.UserMapper; import com.guowuxin.mybatis.model.User;import junit.framework.TestCase;public class TestTwoCache extends TestCase{public static SqlSessionFactory sqlSessionFactory;static{String resource = "mybatis-config.xml";try {InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}@Test public void testCache() { SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();try { UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User u1=mapper1.getUserById(1);System.out.println(u1);sqlSession1.commit();UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);User u2=mapper2.getUserById(1);System.out.println(u2);sqlSession2.commit();} finally { sqlSession1.close(); sqlSession2.close();} } }
在沒有開啟二級緩存之前,將會執行兩次sql語句。
2016-02-24 20:28:10,786 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - PooledDataSource forcefully closed/removed all connections.
2016-02-24 20:28:10,850 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Openning JDBC Connection
2016-02-24 20:28:11,011 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 3874052.
2016-02-24 20:28:11,012 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:28:11,013 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:28:11,030 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-24 20:28:11,040 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Openning JDBC Connection
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 29420695.
2016-02-24 20:28:11,154 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@1c0ec97]
2016-02-24 20:28:11,154 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:28:11,154 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 3874052 to pool.
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1c0ec97]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1c0ec97]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 29420695 to pool.
在實體類映射文件中加入<cache/>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 這里namespace必須是PostsMapper接口的路徑,不然要運行的時候要報錯 “is not known to the MapperRegistry”--> <mapper namespace="com.guowuxin.mybatis.mapper.UserMapper"> <!-- 這兒的resultType是配置在mybatis-config.xml中得別名 --><cache /><select id="getUserById" parameterType="int" resultType="User">select * from user where id=#{id}</select> </mapper>
2016-02-25 10:15:11,162 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 22522451. 2016-02-25 10:15:11,164 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@157aa53] 2016-02-25 10:15:11,164 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=? 2016-02-25 10:15:11,182 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer) id=1,age=0,userName=guowuxin,userAddress=beijing. 2016-02-25 10:15:11,196 main DEBUG (org.apache.ibatis.cache.decorators.LoggingCache) - Cache Hit Ratio [com.guowuxin.mybatis.mapper.UserMapper]: 0.5 id=1,age=0,userName=guowuxin,userAddress=beijing. 2016-02-25 10:15:11,196 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@157aa53] 2016-02-25 10:15:11,196 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@157aa53] 2016-02-25 10:15:11,197 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 22522451 to pool.
就會發現cache命中,只執行了一次sql語句
------------------------------
如果二級緩存想要命中實現,則必須要將上一次sqlSession commit之后才能生效,不然將不會命中,原因:
兩個不同的session必須提交前面一個session才能緩存生效的原因是因為mybatis的緩存會被一個transactioncache類包裝住,所有的cache.putObject全部都會被暫時存到一個map里,等事務提交以后,這個map里的緩存對象才會被真正的cache類執行putObject操作。
總結
以上是生活随笔為你收集整理的mybatis的缓存机制是怎么样的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pat天梯赛L1-055. 谁是赢家
- 下一篇: 互联网晚报 | 3月8日 星期二 |