1.查询缓存
一级缓存:同一个SqlSession对象,MyBatis默认开启一级缓存
如果用同样的SqlSession对象查询相同的数据,则只会在第一次查询时向数据库发送Sql语句并将查询的结果放入到SqlSession中(作为缓存存在),后续再次查询该对象即可(即省略了数据库的访问)
// Connection - SqlSession操作Mybatis // conf.xml->reader Reader reader = Resources.getResourceAsReader("conf.xml"); // reader->sqlSession // 可以通过build的第二参数 指定数据库环境 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader, "development"); SqlSession session = sessionFactory.openSession(); StudentMapper studentMapper = session.getMapper(StudentMapper.class); Student student = studentMapper.queryStudentByStuno(2); Student student2 = studentMapper.queryStudentByStuno(2); //增删改操作... session.commit(); Student student3 = studentMapper.queryStudentByStuno(2); System.out.println(student.getStuName()); System.out.println(student2.getStuName()); System.out.println(student3.getStuName()); session.close(); 结果: DEBUG [main] - ==> Preparing: select * from student1 where stuno=2 DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 DEBUG [main] - ==> Preparing: select * from student1 where stuno=2 DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 ls ls ls
二级缓存:
Mybatis自带二级缓存:同一个namespace生成的XxxMapper对象
MyBatis默认关闭二级缓存,需要手工打开
回顾:namespace的值就是接口的全类名(包名、类名),通过接口可以产生代理对象(Mapper对象)
-->namespace决定了Mapper对象的产生
结论:只要产生的xxxMapper对象来自于同一个namespace,则这些对象共享二级缓存。
如果是同一个SqlSession对象进行多次相同的查询,则直接进入一级缓存查询
如果不是同一个SqlSession对象进行多次相同的查询(但是均来自于同一个namespace),则进入二级缓存查询
// Connection - SqlSession操作Mybatis // conf.xml->reader Reader reader = Resources.getResourceAsReader("conf.xml"); // reader->sqlSession // 可以通过build的第二参数 指定数据库环境 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader, "development"); //第一次查询 SqlSession session = sessionFactory.openSession(); StudentMapper studentMapper = session.getMapper(StudentMapper.class); Student student = studentMapper.queryStudentByStuno(2); //第二次查询 SqlSession session2 = sessionFactory.openSession(); StudentMapper studentMapper2 = session2.getMapper(StudentMapper.class); Student student2 = studentMapper2.queryStudentByStuno(2); System.out.println(student.getStuName()); System.out.println(student2.getStuName()); session.close();
session2.close(); 结果: DEBUG [main] - Opening JDBC Connection DEBUG [main] - Created connection 481511146. DEBUG [main] - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@1cb346ea] DEBUG [main] - ==> Preparing: select * from student1 where stuno=2 DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 DEBUG [main] - Opening JDBC Connection DEBUG [main] - Created connection 1060042118. DEBUG [main] - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@3f2ef586] DEBUG [main] - ==> Preparing: select * from student1 where stuno=2 DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 ls ls 原因:未开启二级缓存
手工开启二级缓存:
a./MyBatisProject3/src/conf.xml
"cacheEnabled" value="true"/>
b.在具体的mapper.xml中声明开启
/MyBatisProject3/src/org/myy/mapper/studentMapper.xml
根据异常提示java.io.NotSerializableException: 可知,MyBatis缓存是将对象放入硬盘文件中
->准备缓存的对象,必须实现了序列化接口(如果开启的缓存namespace="org.myy.mapper.StudentMapper")
可知序列化对象为Student,因此需要将Student序列化(序列化Student类,以及Student的级联属性和父类)
public class Student implements Serializable
...
序列化:内存->硬盘
反序列化:硬盘->内存
触发将对象写入二级缓存的时机:SqlSession对象的close()方法
// Connection - SqlSession操作Mybatis // conf.xml->reader Reader reader = Resources.getResourceAsReader("conf.xml"); // reader->sqlSession // 可以通过build的第二参数 指定数据库环境 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader, "development"); //第一次查询 SqlSession session = sessionFactory.openSession(); StudentMapper studentMapper = session.getMapper(StudentMapper.class); Student student = studentMapper.queryStudentByStuno(2); session.close();//触发将对象写入二级缓存的时机 //第二次查询 SqlSession session2 = sessionFactory.openSession(); StudentMapper studentMapper2 = session2.getMapper(StudentMapper.class); Student student2 = studentMapper2.queryStudentByStuno(2); System.out.println(student.getStuName()); System.out.println(student2.getStuName()); session2.close();
结果:
DEBUG [main] - Cache Hit Ratio [org.myy.mapper.StudentMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 997850486.
DEBUG [main] - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@3b79fd76]
DEBUG [main] - ==> Preparing: select * from student1 where stuno=2
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 1
DEBUG [main] - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@3b79fd76]
DEBUG [main] - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@3b79fd76]
DEBUG [main] - Returned connection 997850486 to pool.
DEBUG [main] - Cache Hit Ratio [org.myy.mapper.StudentMapper]: 0.5
ls
ls
注意:二级缓存的范围是同一个namespace,如果有多个xxMapper.xml的namespace值相同,则通过这些xxxMapper.xml产生的xxMapper对象仍然共享二级缓存
禁用:select标签中useCache="false"
<select id="queryStudentByStuno" parameterType="int" resultMap="studentMapping" useCache="false"> select * from student1 where stuno=${value} select>
清理:a.与清理一级缓存的方法相同
commit();(一般执行增删改时,会清理掉缓存,设计的原因:是为了防止脏数据)
在二级缓存中,commit()不能时查询自身的commit。
commit会清理一级和二级缓存,但是清理二级缓存时,不能是查询自身的commit();
b.在select标签中增加属性flushCache="true"
<select id="queryStudentByStuno" parameterType="int" resultMap="studentMapping" useCache="true" flushCache="true"> select * from student1 where stuno=${value} select>
命中率:1:0.0
2:0.5
3:0.6666666
4.0.75
DEBUG [main] - Cache Hit Ratio [org.myy.mapper.StudentMapper]: 0.0 DEBUG [main] - Opening JDBC Connection DEBUG [main] - Created connection 997850486. DEBUG [main] - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@3b79fd76] DEBUG [main] - ==> Preparing: select * from student1 where stuno=2 DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 DEBUG [main] - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@3b79fd76] DEBUG [main] - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@3b79fd76] DEBUG [main] - Returned connection 997850486 to pool. DEBUG [main] - Cache Hit Ratio [org.myy.mapper.StudentMapper]: 0.5 ls ls DEBUG [main] - Cache Hit Ratio [org.myy.mapper.StudentMapper]: 0.6666666666666666 DEBUG [main] - Cache Hit Ratio [org.myy.mapper.StudentMapper]: 0.75
三方提供的二级缓存:
ehcache、mecache
想要整合三方提供的二级缓存(或者自定义二级缓存),必须实现org.apache.ibatis.cache.Cache接口,该接口的默认实现类是PerpetCache
整合ehcache二级缓存:
a.添加jar包
Ehcache-core.jar
mybatis-Ehcache.jar
slf4j-api.jar
b.编写ehcache配置文件 Ehcache.xml
"1.0" encoding="UTF-8"?>"http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> "D:\test\Ehcache"/> <defaultCache maxElementsInMemory="10000" maxElementsOnDisk="1000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="100" timeToLiveSeconds="100" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/> <cache name="cloud_user" eternal="false" maxElementsInMemory="5000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" memoryStoreEvictionPolicy="LRU"/>
c.开启EhCache二级缓存
/MyBatisProject3/src/Ehcache.xml
"org.mybatis.caches.ehcache.EhcacheCache"> "maxElementsInMemory" value="1000"/>
2.逆向工程
表、类、接口、mapper.xml四者密切相关,因此当知道一个的时候,其他三个应该可以自动生成。
表->其他三个
a.mybatis-generaotr-core.jar、mybatis.jar、ojdbc.jarS
b.逆向工程的配置文件generator.xml
/MyBatisgenerator/src/generator.xml
"1.0" encoding="UTF-8"?> DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">"DB2Tables" targetRuntime="MyBatis3"> "suppressAllComments" value="true" /> "oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:mldn" userId="scott" password="tiger"> "forceBigDecimals" value="false" /> "org.myy.entity" targetProject=".\src"> "trimStrings" value="true" /> "org.myy.mapper" targetProject=".\src"> "XMLMAPPER" targetPackage="org.myy.mapper" targetProject=".\src"> "Student1">
"studentCard">
"studentClass">
/MyBatisgenerator/src/org/myy/test/Test.java
package org.myy.test; import java.io.File; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.exception.XMLParserException; import org.mybatis.generator.internal.DefaultShellCallback; public class Test { public static void main(String[] args) throws Exception, XMLParserException { File file=new File("src/generator.xml");//配置文件 Listwarnings=new ArrayList (); ConfigurationParser cp=new ConfigurationParser(warnings); Configuration config=cp.parseConfiguration(file); DefaultShellCallback callback=new DefaultShellCallback(true); //逆向工程的核心类 MyBatisGenerator generator=new MyBatisGenerator(config,callback,warnings); generator.generate(null); } }