文章目录
Mybatis基础(五)
MyBatis缓存和逆向工程
缓存
-
什么是缓存(概念)
缓存就是数据交换的缓冲区(Cache) 缓冲区可以是数组或集合,也可以理解为一个中间容器。 存在内存中的数据。
-
为什么使用缓存
减少和数据库交互的次数,减小系统开销,提高系统查询效率。
-
怎样的数据需要用到缓存
经常查询且不经常改变的数据,通常放在缓存中。
MyBatis一级缓存
-
一级缓存 :同一个SqlSession对象。
MyBatis默认开启一级缓存,如果用同一个的SqlSession对象查询相同的数据, 则只会在第一次查询时,向数据库发送SQL语句,并将查询的结果 放入到SQLSESSION中(作为缓存存在); 后续再次查询该同样的对象时, 则直接从缓存中查询该对象即可(即省略了数据库的访问)。
MyBatis二级缓存
-
【同一个namespace】生成的代理对象(mapper对象)
只要产生的xxxMapper对象,来自于同一个namespace,则这些对象共享二级缓存。 注意:二级缓存的范围是,同一个namespace, 如果有多个xxxMapper.xml的namespace值相同, 则通过这些xxxMapper.xml产生的xxMapper对象(代理对象) 仍然共享二级缓存。 MyBatis默认情况没有开启二级缓存,需要手工打开。 namespace的值,就是【接口的全类名(包名.类名)】, 通过接口可以产生代理对象(xxxMapper对象) 即:namespace决定了xxxMapper对象的产生
使用二级缓存的步骤
-
在
conf.xml
配置文件中,开启二级缓存<configuration> <!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> </configuration>
-
在具体的
mapper.xml
文件中声明开启二级缓存<mapper namespace="org.lanqiao.mapper.StudentMapper"> <!-- 声明次namespace开启二级缓存 --> <cache/> </mapper>
-
注意事项
准备缓存的对象,必须实现了序列化接口(java.io.serializable), 该对象的级联属性和直接父类,也要实现序列化接口(java.io.serializable)。
-
MyBatis的二级缓存 是将对象,放入硬盘文件中(序列化)
-
触发将对象写入二级缓存的时机:SqlSession对象的close()方法
-
回顾
序列化:内存 -> 硬盘(将数据写入到硬盘上) 反序列化:硬盘 -> 内存(将数据读取到内存中)
关闭二级缓存
<!-- 禁用此 select 的二级缓存:useCache="false" -->
<select id="queryStudentByStuno" parameterType="int" resultMap="studentMapping" useCache="false">
select * from student where stuno = ${value}
</select>
清理二级缓存
- 清理缓存的第一种方式:执行增删改操作的SqlSession对象调用
commit()
方法
commit(); (一般执行增删改时 会清理掉缓存;设计的原因 是为了防止脏数据)
在二级缓存中,commit()不能是查询自身的commit,
即:commit()方法是执行增删改操作的 SqlSession 对象所调用的
- 清理缓存的第二种方式:在select标签中 增加属性 flushCache=“true”
<!-- 清理缓存的第二种方式:在select标签中 增加属性 flushCache="true" -->
<select id="queryStudentByStuno" parameterType="int" flushCache="true" resultMap="studentMapping" useCache="true">
select * from student where stuno = ${value}
</select>
第三方缓存
如:ehcache、memcache
- 要想整合三方提供的二级缓存 (或者自定义二级缓存),必须实现
org.apache.ibatis.cache.Cache
接口,该接口的默认实现类是PerpetualCache
。
整合ehcache二级缓存步骤
-
导入jar包
ehcache-core.jar
mybatis-Ehcache.jar
slf4j-api.jar
-
编写ehcache配置文件
Ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!--当二级缓存的对象 超过内存限制时(缓存对象的个数>maxElementsInMemory),存放入的硬盘文件 --> <diskStore path="D:\Ehcache"/> <!-- maxElementsInMemory:设置 在内存中缓存 对象的个数 maxElementsOnDisk:设置 在硬盘中缓存 对象的个数 eternal:设置缓存是否 永远不过期 overflowToDisk:当内存中缓存的对象个数 超过maxElementsInMemory的时候,是否转移到硬盘中 timeToIdleSeconds:当2次访问 超过该值的时候,将缓存对象失效 timeToLiveSeconds:一个缓存对象 最多存放的时间(生命周期) diskExpiryThreadIntervalSeconds:设置每隔多长时间,通过一个线程来清理硬盘中的缓存 memoryStoreEvictionPolicy:当超过缓存对象的最大值时,处理的策略;LRU,FIFO,LFU --> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="1000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="100" timeToLiveSeconds="100" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
-
在要使用EhCache二级缓存的xxxMapper.xml中,开启EhCache二级缓存
<mapper namespace="org.lanqiao.mapper.StudentMapper"> <!-- 声明次namespace开启二级缓存,MyBatis自带的二级缓存 <cache/> --> <cache type="org.mybatis.caches.ehcache.EhcacheCache"> <!-- 通过property覆盖Ehcache.xml中的值 --> <property name="maxElementsInMemory" value="2000"/> <property name="maxElementsOnDisk" value="3000"/> </cache> </mapper>
MyBatis逆向工程(一般不用)
表、类、接口、mapper.xml四者密切相关,因此 当知道一个的时候 其他三个应该可以自动生成。
一般是根据数据库表生成其他三个。
逆向工程使用步骤
-
导入jar包
mybatis-generator-core.jar
mybatis.jar
ojdbc.jar
-
编写逆向工程的配置文件
generator.xml
(通常放在src
类路径下)<?xml version="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"> <generatorConfiguration> <context id="DB2Tables" targetRuntime="MyBatis3"> <commentGenerator> <!-- suppressAllComments属性值: true: 自动生成实体类、SQL映射文件时没有注释 false: 自动生成实体类、SQL映射文件,并附有注释 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 数据库连接信息 --> <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:ORCL" userId="scott" password="tiger"> </jdbcConnection> <!-- forceBigDecimals属性值: true:把数据表中的DECIMAL和NUMERIC类型,解析为JAVA代码中的java.math.BigDecimal类型 false(默认):把数据表中的DECIMAL和NUMERIC类型,解析为解析为JAVA代码中的Integer类型 --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject属性值:实体类的生成位置 targetPackage属性值:实体类所在包的路径 --> <javaModelGenerator targetPackage="org.lanqiao.entity" targetProject=".\src"> <!-- trimStrings属性值: true:对数据库的查询结果进行trim操作 false(默认):不进行trim操作 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject属性值:SQL映射文件的生成位置 targetPackage属性值:SQL映射文件所在包的路径 --> <sqlMapGenerator targetPackage="org.lanqiao.mapper" targetProject=".\src"> </sqlMapGenerator> <!-- 生成动态代理的接口 --> <javaClientGenerator type="XMLMAPPER" targetPackage="org.lanqiao.mapper" targetProject=".\src"> </javaClientGenerator> <!-- 指定数据库表 --> <table tableName="Student"> </table> <table tableName="studentCard"> </table> <table tableName="studentClass"> </table> </context> </generatorConfiguration>
-
编写主方法,执行
package org.lanqiao.test; import java.io.File; import java.io.IOException; import java.sql.SQLException; 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.InvalidConfigurationException; import org.mybatis.generator.exception.XMLParserException; import org.mybatis.generator.internal.DefaultShellCallback; public class Test { public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException { File file = new File("src/generator.xml") ;//配置文件 List<String> warnings = 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); } }