MyBatis 缓 存
一.缓存
1.应用程序和数据库交互的过程是一个相比较耗时的过程。
2.缓存存在意义:让应用程序减少对数据库的访问,提升程序运行效率。
3.缓存是基于查询之上的。MyBatis中分一级缓存(SqlSession缓存)和二级缓存(SqlSessionFactory缓存)。
二.SqlSession缓存
1.MyBatis中SqlSession缓存是默认开启的。缓存的是statement对象。在mybatis.xml中一个< select >对应一个statement对象
2.执行sql语句时缓存流程:
(1) 先去缓存区中找是否存在statement
(2) 返回结果
(3) 如果没有缓存statement对象,则去数据库中获取数据
(4) 数据库返回查询结果
(5) 把查询结果放到对应的缓存区中
[外链图片转存失败(img-la2sel7w-1563867673477)(https://i.imgur.com/VkySvPb.png)]
3.同一SqlSession对象调用同一 < select > 时,只有第一次访问数据库,第一次之后把查询结果缓存到SqlSession缓存区(内存)中。
代码示例:
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
session.selectList("com.tit.mapper.LogMapper.selAll");
session.selectList("com.tit.mapper.LogMapper.selAll");
}
执行的sql:
`org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.0
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Preparing: select * from log
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Parameters:
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG <== Total: 16
org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.0`
注:同一SqlSession对象调用相同的< select >,只产生一个stetement对象。
4.缓存的是statement对象。在mybatis.xml中一个< select >对应一个statement对象。
代码示例:
public static void main(String[] args) throws IOException { InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
session.selectList("com.tit.mapper.LogMapper.selAll");
session.selectList("com.tit.mapper.LogMapper.selAllTO");
}
mapper.xml中:
< mapper namespace=“com.tit.mapper.LogMapper” >
< select id=“selAll” resultType=“log” >
select * from log
< /select>
< select id=“selAllTO” resultType=“log”>
select * from log
< /select>
< /mapper>
执行的sql:
`org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.0
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Preparing: select * from log
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Parameters:
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG <== Total: 16
org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.0
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Preparing: select * from log
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Parameters:
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG <== Total: 16 `
注:同一SqlSession对象调用不同的< select >,产生两个stetement对象。
三.SqlSessionFactory缓存
1.实现多个SqlSession对象共享数据(session.close()后,SqlSession缓存的内容刷到SqlSessionFactory中)。
2.当数据频繁被使用,却很少被修改时,才使用SqlSessionFactory缓存,否则会读取到脏数据。
3.使用步骤:在mapper.xml中添加 < cache readOnly=“true”>< /cache>
其中readOnly=“true” 表示是否对二级缓存数据进行读取。若不加readOnly=“true”,则将所有实体类序列化也可开启二级缓存。
注:序列化与反序列化:
[外链图片转存失败(img-WQgH3dTa-1563867673480)(https://i.imgur.com/LmXKRtH.png)]
一个类序列化之后,类中所有数据就允许从临时数据保存至硬盘上。
4.代码示例:
不同SqlSession对象调用同一 < select> :
`public static void main(String[] args) throws IOException { InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
SqlSession session = factory.openSession();
session.selectList("com.tit.mapper.LogMapper.selAll");
session.close();
SqlSession session1 = factory.openSession();
session1.selectList("com.tit.mapper.LogMapper.selAll");
session1 .close();
}`
mapper.xml中:
`< mapper namespace="com.tit.mapper.LogMapper" >
< cache readOnly="true">< /cache>
< select id="selAll" resultType="log" statementType="PREPARED">
select * from log
</ select>
< select id="selAllTO" resultType="log">
select * from log
< /select>
< /mapper>`
执行的sql:
`org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.0
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Preparing: select * from log
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Parameters:
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG <== Total: 16
org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.5`
四.一级缓存和二级缓存
1.当Sqlsession对象commit()或close()时,会把Sqlsession缓存的数据刷(flush)到SqlSessionFactory的缓存区中。
2.将上面代码修改如下:
将session.close();注释
`public static void main(String[] args) throws IOException { InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
session.selectList("com.tit.mapper.LogMapper.selAll");
//session.close();
SqlSession session1 = factory.openSession();
session1.selectList("com.tit.mapper.LogMapper.selAll");
session1 .close();
}`
mapper.xml不变,执行的sql:
`org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.0
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Preparing: select * from log
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG ==> Parameters:
org.apache.ibatis.logging.jdbc.BaseJdbcLogger DEBUG <== Total: 16
org.apache.ibatis.cache.decorators.LoggingCache DEBUG Cache Hit Ratio [com.tit.mapper.LogMapper]: 0.5 `
3.流程图:
[外链图片转存失败(img-6khfBzWg-1563867673481)(https://i.imgur.com/Aya2Pfr.png)]
注:将session.close();注释后,SqlSession缓存的内容并没有刷到SqlSessionFactory中,所以产生两个statement对象。
五.补充
statementType=“CALLABLE”
“PREPARED” -默认值
“STATEMENT”
statement:执行sql的执行器
CALLABLE:JDBC中执行存储过程的执行器
PREPARED:PREPARED接口是接口STATEMENT的子接口,解决了STATEMENT的sql注入问题。
2.Connection conn=null;
conn.prepareStatement("");
conn.createStatement("");
"STATEMENT"
statement:执行sql的执行器
CALLABLE:JDBC中执行存储过程的执行器
PREPARED:PREPARED接口是接口STATEMENT的子接口,解决了STATEMENT的sql注入问题。
2.Connection conn=null;
conn.prepareStatement("");
conn.createStatement("");
conn.prepareCall("");//调用存储过程的方法