数据库中数据虽多,但访问频率却不同,有的数据1s内就会有多次访问,而有些数据几天都没人查询,这时候就可以将访问频率高的数据放到缓存中,就不用去数据库里取了,提高了效率还节约了数据库资源

MyBatis有两种缓存,分为一级和二级缓存。

一级缓存作用域为SqlSession,同一个SqlSession才能访问到,采用HashMap存储数据,当该SqlSession进行了DML操作或者调用close()方法,其中的一级缓存就会清空。一级缓存默认开启。

二级缓存的作用域是mapper映射配置文件,多个SqlSession共用二级缓存,二级缓存仍然使用HashMap存储数据,如果多个SqlSession执行同一个命名空间的同一条sql,且传入的参数也相同,就是说最终执行相同的sql的话,就会从二级缓存中拿数据。二级缓存需要配置,默认不开启

一级缓存

sql映射器配置xml文件:

<mapper namespace="net.sonng.mbt.mapper.BookMapper">
<select id="findAll" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book
</select> <select id="findBookById" parameterType="int" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book WHERE id=#{id}
</select> <update id="updateBook" parameterType="net.sonng.mbt.entity.Book" >
UPDATE book
<set>
<if test="name!=null" >`name`=#{name},</if>
<if test="press!=null" >press=#{press},</if>
<if test="author!=null" >author=#{author},</if>
<if test="isbn!=null" >isbn=#{isbn},</if>
<if test="douban!=null" >douban=#{douban}</if>
</set>
WHERE id=${id}
</update>
<select id="findBookInId" parameterType="list" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book WHERE id In
<foreach item="id" index="i" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>

映射器接口略

测试类:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class BookTest {
public static void main(String[] args) throws IOException{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session=sqlSessionFactory.openSession();
BookMapper bookMapper=session.getMapper(BookMapper.class); Book book0=bookMapper.findBookById(5); //第一次查询
System.out.println(book0); Book book1=bookMapper.findBookById(5); //同样的语句,第二次查询
System.out.println(book1);
book1.setDouban(9.9f);
bookMapper.updateBook(book1); //DML语句,更改了数据
session.commit(); //注意这里,有没有commit效果一样,都会更新数据库,清除一级缓存 Book book2=bookMapper.findBookById(5); //同样的语句,第三次查询
System.out.println(book2);
session.close();
}
}

输出如下:

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=? //第一次查询

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=9.9]

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=9.9] //第二次查询,没有执行sql语句,直接从SqlSession一级缓存中拿到数据

DEBUG [main] - ==> Preparing: UPDATE book SET name=?, press=?, author=?, isbn=?, douban=? WHERE id=5 //更新了数据

DEBUG [main] - > Parameters: 深入理解Java 7 核心技术与最佳实践(String), 机械工业出版社(String), 成富著(String), 9787111380399(String), 9.9(Float) //update语句清空了一级缓存

DEBUG [main] - < Updates: 1

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=? //第三次查询,一级缓存已被情况,执行sql语句入库查询

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=9.9]

测试结论之一:不管前面的查询有没有提交事务,查询结果都会写到一级缓存中;如果session执行了DML,一级缓存会被清空

特别注意的是:要是同一条sql语句才会从缓存中拿数据,比如看下面的测试代码:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class BookTest {
public static void main(String[] args) throws IOException{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session=sqlSessionFactory.openSession();
BookMapper bookMapper=session.getMapper(BookMapper.class);
List<Integer> ids=new ArrayList<Integer>();
ids.add(1);
ids.add(2);
ids.add(4);
ids.add(5);
List<Book> books0=bookMapper.findBookInId(ids); //第一次查询
for(Book b:books0){
System.out.println(b);
} List<Book> books1=bookMapper.findBookInId(ids); //同一条语句,第二次查询
for(Book b:books1){
System.out.println(b);
} Book book0=bookMapper.findBookById(5); //虽然缓存中有这条记录,但还是执行了一次sql查询
System.out.println(book0); session.close();
}
}

输出如下:

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id In ( ? , ? , ? , ? ) //第一次查询

DEBUG [main] - > Parameters: 1(Integer), 2(Integer), 4(Integer), 5(Integer)

DEBUG [main] - < Total: 4

Book [id=1, name=深入理解Java虚拟机 JVM高级特性与最佳实践, press=机械工业出版社, author=周志明著, isbn=9787111421900, douban=8.8]

Book [id=2, name=疯狂Java讲义 第3版, press=电子工业出版社, author=李刚著, isbn=9787121236693, douban=7.8]

Book [id=4, name=Java编程思想 第4版, press=机械工业出版社, author=(美)Bruce Eckel著, isbn=9787111213826, douban=9.1]

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=9.9]

Book [id=1, name=深入理解Java虚拟机 JVM高级特性与最佳实践, press=机械工业出版社, author=周志明著, isbn=9787111421900, douban=8.8] //同一条语句,第二次查询,从缓存中拿数据,没有执行新的sql查询

Book [id=2, name=疯狂Java讲义 第3版, press=电子工业出版社, author=李刚著, isbn=9787121236693, douban=7.8]

Book [id=4, name=Java编程思想 第4版, press=机械工业出版社, author=(美)Bruce Eckel著, isbn=9787111213826, douban=9.1]

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=9.9]

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=? //其实要查询的数据在缓存已经存在,但是还是执行了一次查询

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=9.9]

测试结论之二:要最终执行相同的sql语句,才会到一级缓存中拿数据

MyBatis使用HashMap存储缓存信息,key根据查询出来的对象生成,value是查询出来的对象

使用一级缓存要特别注意:缓存的作用范围是SqlSession,假如SqlSessionA中已经有了一级缓存,而SqlSessionB修改了数据库的数据,此时SqlSessionA再执行相同查询,会从SqlSessionA的一级缓存中拿数据,导致跟数据库中的不同。关于这一点,是否有别的配置可以解决,还没见到,或许要通过编程解决,看下面的测试代码:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class BookTest {
public static void main(String[] args) throws IOException{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session1=sqlSessionFactory.openSession(); BookMapper bookMapper1=session1.getMapper(BookMapper.class);
Book book1=bookMapper1.findBookById(5); //session1的第一次查询,入库查询
System.out.println(book1);
Book book2=bookMapper1.findBookById(5); //session1的第二次查询,从一级缓存中拿数据
System.out.println(book2); SqlSession session2=sqlSessionFactory.openSession();
BookMapper bookMapper2=session2.getMapper(BookMapper.class);
Book book3=bookMapper2.findBookById(5); //session2的第一次查询,入库查询
book3.setDouban(10.0f);
bookMapper2.updateBook(book3);
session2.commit(); //session2修改了数据库中的数据,并且提交了事务
Book book4=bookMapper2.findBookById(5); //session2的第二次查询,入库查询
System.out.println(book4);
session2.commit(); Book book5=bookMapper1.findBookById(5); //session1的第三次查询,从一级缓存中拿到过时的数据
System.out.println(book5);
}
}

输出如下:

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=? //session1第一次查询,执行sql,入库查询

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9]

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9] //session1第二次查询,从一级缓存中拿数据

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=? //session2第一次查询,执行sql,入库查询

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

DEBUG [main] - ==> Preparing: UPDATE book SET name=?, press=?, author=?, isbn=?, douban=? WHERE id=5 //session2修改了数据库的数据,且提交了事务

DEBUG [main] - > Parameters: 深入理解Java 7 核心技术与最佳实践(String), 机械工业出版社(String), 成富著(String), 9787111380399(String), 10.0(Float)

DEBUG [main] - < Updates: 1

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=? //session2第二次查询,执行sql,入库查询

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0] //由此可以看出,数据库中的数据已经被修改

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9] //session1第三次查询,从一级缓存中拿到了过时的数据

测试结论之三:sessionA修改了数据库的数据,不会影响到sessionB的一级缓存数据

二级缓存

二级缓存是跨SqlSession的,其作用范围是同一个mapper映射文件,就是同一个命名空间。

MyBatis默认开启一级缓存,但没有开启二级缓存,因此还需要配置

在mybatis-config.xml的settings元素中开启二级缓存

    <settings>
<setting name="logImpl" value="LOG4J" />
<setting name="cacheEnabled" value="true" />
</settings>

因为二级缓存是基于mapper映射文件的,因此映射文件中还要进行一些配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTDMapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="net.sonng.mbt.mapper.BookMapper">
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true" /> <!-- 二级缓存配置 -->
<select id="findAll" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book
</select> <select id="findBookById" parameterType="int" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book WHERE id=#{id}
</select>
<select id="findBooks" parameterType="net.sonng.mbt.entity.Book" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book WHERE
<choose>
<when test="isbn!=null" >
isbn=#{isbn}
</when>
<when test="name!=null">
`name`=#{name}
</when>
<otherwise>
douban&gt;7
</otherwise>
</choose>
</select> <update id="updateBook" parameterType="net.sonng.mbt.entity.Book" >
UPDATE book
<set>
<if test="name!=null" >`name`=#{name},</if>
<if test="press!=null" >press=#{press},</if>
<if test="author!=null" >author=#{author},</if>
<if test="isbn!=null" >isbn=#{isbn},</if>
<if test="douban!=null" >douban=#{douban}</if>
</set>
WHERE id=${id}
</update>
<select id="findBookInId" parameterType="list" resultType="net.sonng.mbt.entity.Book">
SELECT * FROM book WHERE id In
<foreach item="id" index="i" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select> <select id="findBookLikeName" parameterType="string" resultType="net.sonng.mbt.entity.Book">
<bind name="pattern" value="'%'+_parameter+'%'" />
SELECT * FROM book WHERE `name` LIKE #{pattern}
</select>
</mapper>

cache元素的几个属性:

----flushInterval:刷新间隔,单位毫秒。默认不设置,即不刷新,仅在调用语句时刷新。

----size:缓存的数目,默认1024

----readOnly:是否只读,默认false。true表示多次查询时返回的是这个对象的引用;false表示返回的是对象的拷贝

----eviction:收回策略,默认LRU。

--------LRU:最近最少使用策略,移除长时间不被使用的对象

--------FIFO:先进先出策略,按对象进入缓存的顺序移除

--------SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象

--------WEAK:弱引用策略

实体类还要实现Serializable接口

二级缓存测试之一:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class BookTest {
public static void main(String[] args) throws IOException{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); SqlSession session1=sqlSessionFactory.openSession();
BookMapper bookMapper1=session1.getMapper(BookMapper.class);
Book book1=bookMapper1.findBookById(5); //第一次查询
System.out.println(book1);
session1.commit(); //session1提交事务,特别注意:如果这里不commit,那么没有二级缓存 SqlSession session2=sqlSessionFactory.openSession();
BookMapper bookMapper2=session2.getMapper(BookMapper.class);
Book book2=bookMapper2.findBookById(5); //第二次查询
System.out.println(book2);
session2.close();
session1.close();
}
}

输出如下:

DEBUG [main] - Cache Hit Ratio [net.sonng.mbt.mapper.BookMapper]: 0.0 //session1第一次查询,二级缓存中没有数据

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=?

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0]

DEBUG [main] - Cache Hit Ratio [net.sonng.mbt.mapper.BookMapper]: 0.5 //session2第一次查询,从二级缓存中命中数据

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0]

测试结论之四:sessionA执行一次查询,如果提交了事务,查询的结果会写到二级缓存中,sessionB执行相同查询,会查询到二级缓存中的数据。注意要提交事务才会写到二级缓存中。

二级缓存测试之二:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class BookTest {
public static void main(String[] args) throws IOException{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); SqlSession session1=sqlSessionFactory.openSession();
BookMapper bookMapper1=session1.getMapper(BookMapper.class);
Book book1=bookMapper1.findBookById(5); //session1第一次查询
System.out.println(book1);
session1.commit();
book1.setDouban(10.0f);
bookMapper1.updateBook(book1); //session1修改了数据
session1.commit(); //标注一。 SqlSession session2=sqlSessionFactory.openSession();
BookMapper bookMapper2=session2.getMapper(BookMapper.class);
Book book2=bookMapper2.findBookById(5); //session2第一次查询
System.out.println(book2);
session2.close();
}
}

输出如下:

DEBUG [main] - Cache Hit Ratio [net.sonng.mbt.mapper.BookMapper]: 0.0

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=?

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9]

DEBUG [main] - ==> Preparing: UPDATE book SET name=?, press=?, author=?, isbn=?, douban=? WHERE id=5

DEBUG [main] - > Parameters: 深入理解Java 7 核心技术与最佳实践(String), 机械工业出版社(String), 成富著(String), 9787111380399(String), 10.0(Float)

DEBUG [main] - < Updates: 1

DEBUG [main] - Cache Hit Ratio [net.sonng.mbt.mapper.BookMapper]: 0.0 //session2的第一次查询,没有命中,需要入库查询,说明session1的update语句清除了二级缓存

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=?

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0]

如果把测试代码二的标注一这行代码注释掉的话,也就是不提交事务,输出如下:

DEBUG [main] - Cache Hit Ratio [net.sonng.mbt.mapper.BookMapper]: 0.0

DEBUG [main] - ==> Preparing: SELECT * FROM book WHERE id=?

DEBUG [main] - > Parameters: 5(Integer)

DEBUG [main] - < Total: 1

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9]

DEBUG [main] - ==> Preparing: UPDATE book SET name=?, press=?, author=?, isbn=?, douban=? WHERE id=5

DEBUG [main] - > Parameters: 深入理解Java 7 核心技术与最佳实践(String), 机械工业出版社(String), 成富著(String), 9787111380399(String), 10.0(Float)

DEBUG [main] - < Updates: 1

DEBUG [main] - Cache Hit Ratio [net.sonng.mbt.mapper.BookMapper]: 0.5 //session2的第一次查询,命中了数据,二级缓存中还有数据

Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0]

再看数据库,数据并没有被修改,这里出现了脏读。没有提交事务,这里的update语句只修改了缓存中的数据,数据库中的数据并没有修改,另一个sqlSession脏读到了缓存中的数据。

测试结论之五:sessionA如果执行了DML操作且提交了事务,会清空二级缓存;如果只执行DML操作但不提交事务,那么会修改二级缓存中的数据,而不会实际修改数据库的数据,这时候会导致sessionA或其他session的脏读。

实际上只要该mapper命名空间下的sql执行了DML并提交事务,该命名空间的二级缓存都会清空。

小结

一级缓存默认开启,二级缓存默认不开启,需要到MyBatis-config.xml中开启

一级缓存的作用范围是SqlSession,二级缓存是跨SqlSession的,是mapper映射文件级别的

一级缓存不管是否提交事务,前面的查询结果都会写到一级缓存中;但二级缓存有区别,前面的查询提交了事务,才会把结果写到二级缓存中

一级缓存会在session执行了DML时清空

二级缓存会在命名空间下的DML语句被执行并提交了事务时清空

顺序:二级缓存、一级缓存、入库查询

其他:

CSDN 《深入理解mybatis原理》 MyBatis的二级缓存的设计原理

CSDN mybatis 一级缓存和二级缓存简介

0065 MyBatis一级缓存与二级缓存的更多相关文章

  1. [原创]关于mybatis中一级缓存和二级缓存的简单介绍

    关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...

  2. MyBatis 延迟加载,一级缓存,二级缓存设置

    什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...

  3. mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存

    设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --> <settings ...

  4. 9.Mybatis一级缓存和二级缓存

    所谓的缓存呢?其实原理很简单,就是在保证你查询的数据是正确的情况下,没有去查数据库,而是直接查找的内存,这样做有利于缓解数据库的压力,提高数据库的性能,Mybatis中有提供一级缓存和二级缓存. 学习 ...

  5. 八 mybatis查询缓存(一级缓存,二级缓存)和ehcache整合

    1       查询缓存 1.1     什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存.

  6. myBatis学习(9):一级缓存和二级缓存

    正如大多数持久层框架一样,MyBatis同样提供了一级缓存和二级缓存的支持 1. MyBatis一级缓存基于PerpetualCache的HashMap本地缓存,其存储作用域为 Session,默认情 ...

  7. mybatis 详解(九)------ 一级缓存、二级缓存

    上一章节,我们讲解了通过mybatis的懒加载来提高查询效率,那么除了懒加载,还有什么方法能提高查询效率呢?这就是我们本章讲的缓存. mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解 ...

  8. MyBatis从入门到放弃六:延迟加载、一级缓存、二级缓存

    前言 使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载.一级缓存.二级缓存.使用时需要注意延迟加载必须使用resultMa ...

  9. Mybatis第八篇【一级缓存、二级缓存、与ehcache整合】

    Mybatis缓存 缓存的意义 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题. myba ...

随机推荐

  1. GPGPU OpenCL编程步骤与简单实例

    http://www.cnblogs.com/xudong-bupt/p/3582780.html  1.OpenCL概念 OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU.GPU或其 ...

  2. RV BaseRecyclerViewAdapterHelper 总结 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. 利用js动态创建<style>

    var nod = document.createElement(“style”), str = “body{background:#000;color:#fff} a{color:#fff;text ...

  4. Code a simple telnet client using sockets in python

    测试端口是否开放的python脚本 原文: https://www.binarytides.com/code-telnet-client-sockets-python/ 配置: 120.79.14.8 ...

  5. MySQL for Mac安装和启动

    MySQL for Mac安装和启动 学习了:https://blog.csdn.net/a380880304/article/details/49840139 注意密码是数字1还是字母l: 系统提示 ...

  6. (LeetCode 53)Maximum Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  7. NCBI SRA数据预处理

    SRA数据的的处理流程大概如下 一.SRA数据下载. NCBI 上存储的数据现在大都存储为SRA格式. 下载以后就是以SRA为后缀名. 这里可以通过三种方式下载SRA格式的数据. 1.通过http方式 ...

  8. 缺少网络连接需要的Windows套接字注册表项(浏览器无法连网)

      缺少网络连接需要的Windows套接字注册表项(浏览器无法连网) CreateTime--2018年4月25日14:17:42 Author:Marydon 1.异常信息 此计算机上缺少一个或多个 ...

  9. jquery 图片懒加载

      jquery 图片懒加载 CreationTime--2018年7月1日14点45分 Author:Marydon 1.源码展示 (function(a){a.fn.lazyload=functi ...

  10. 解决在sdk manager中更新文件后出现This Android SDK requires Android Developer Toolkit version 23.1的错误

    起因:在sdksdk manager中更新了adt及其它的支持库后,eclipse报错:This Android SDK requires Android Developer Toolkit vers ...