11.4 注解使用二级缓存
项目结构
展开/折叠
G:\workspace_web2\MyATwoLevelCacheTest
├─src\
│ ├─db.properties
│ ├─domain\
│ │ └─User.java
│ ├─fractory\
│ │ └─SqlSessionFactoryTools.java
│ ├─log4j.xml
│ ├─mapper\
│ │ └─UserMapper.java
│ ├─mybatis-config.xml
│ ├─tb_user.sql
│ └─test\
│ ├─DeleteUserTest.java
│ └─SelectTest.java
└─WebContent\
├─META-INF\
│ └─MANIFEST.MF
└─WEB-INF\
└─lib\
├─commons-logging-1.2.jar
├─log4j-1.2.17.jar
├─log4j-api-2.3.jar
├─log4j-core-2.3.jar
├─mybatis-3.4.5.jar
└─mysql-connector-java-5.1.44-bin.jar
数据库表
/MyATwoLevelCacheTest/src/tb_user.sql1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(18) DEFAULT NULL, `sex` char(2) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) );
INSERT INTO `tb_user` VALUES ('1', '小明', '男', '21'); INSERT INTO `tb_user` VALUES ('2', '小王', '男', '22'); INSERT INTO `tb_user` VALUES ('3', '小丽', '女', '18'); INSERT INTO `tb_user` VALUES ('4', '小芳', '女', '18'); INSERT INTO `tb_user` VALUES ('5', '小王', '男', '22');
|
mybatis相关配置
db.properties
/MyATwoLevelCacheTest/src/db.properties1 2 3 4 5 6 7 8 9
|
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis username=root password=root
|
log4j.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//LOG4J//DTD LOG4J//EN" "https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd" >
<log4j:configuration> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%5p [%t] %m%n" /> </layout> </appender> <logger name="mapper.UserMapper"> <level value="DEBUG" /> </logger> <root> <level value="ERROR" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>
|
mybatis-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?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> <properties resource="db.properties" /> <settings> <setting name="logImpl" value="log4j" /> </settings> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="pooled"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper class="mapper.UserMapper" /> </mappers> </configuration>
|
持久化对象
/MyATwoLevelCacheTest/src/domain/User.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package domain; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 2667279148834038605L; private Integer id; private String name; private String sex; private Integer age; public User() {} @Override public String toString() { return "User [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + "]"; } }
|
mapper接口
/MyATwoLevelCacheTest/src/mapper/UserMapper.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package mapper;
import java.util.List; import org.apache.ibatis.annotations.CacheNamespace; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.cache.decorators.LruCache; import domain.User;
@CacheNamespace( eviction = LruCache.class, flushInterval = 60000, size = 512, readWrite = true ) public interface UserMapper {
@Select("select * from tb_user where id=#{id}") @Options(useCache = true) User selectUserById(Integer id);
@Select("select * from tb_user") @Options(useCache = true) List<User> selectAllUsers();
@Delete("delete from tb_user where id=#{id}") void deleteUserById(Integer id); }
|
UserMapper
接口中只是将之前写在XML
文件当中的二级缓存配置写在了注解当中,其他并无不同。
@CacheNamespace注解
@CacheNamespace
注解用来配置二级缓存,如下所示:
1 2 3 4 5 6
| @CacheNamespace( eviction = LruCache.class, flushInterval = 60000, size = 512, readWrite = true )
|
eviction
属性表示要使用的回收策略的class
,所有回收策略的类型都位于org.apache.ibatis.cache.decorators
包下。
flushInterval
表示刷新时间间隔,单位为毫秒
size
表示缓存数目
readWrite=true
表示只读
SqlSession工厂类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package fractory;
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;
public class SqlSessionFactoryTools { private static SqlSessionFactory sqlSessionFactory = null; static { try { InputStream mybatisConfigXML = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(mybatisConfigXML);
} catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
|
测试类
按id查询SelectTest.java
/MyATwoLevelCacheTest/src/test/SelectTest.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package test; import org.apache.ibatis.session.SqlSession; import domain.User; import fractory.SqlSessionFratoryTools; import mapper.UserMapper; public class SelectTest{ public static void main(String[] args) { SqlSession sqlSession = null; try { sqlSession = SqlSessionFratoryTools.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.selectUserById(1); System.out.println(user); sqlSession.close(); sqlSession = SqlSessionFratoryTools.getSqlSession(); userMapper = sqlSession.getMapper(UserMapper.class); System.out.println("-----------------------------------------------"); user = userMapper.selectUserById(1); System.out.println(user); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if(sqlSession != null) sqlSession.close(); } } }
|
运行效果:
1 2 3 4 5 6 7 8
| DEBUG [main] Cache Hit Ratio [mapper.UserMapper]: 0.0 DEBUG [main] ==> Preparing: select * from tb_user where id=? DEBUG [main] ==> Parameters: 1(Integer) DEBUG [main] <== Total: 1 User [id=1, name=小明, sex=男, age=21] ----------------------------------------------- DEBUG [main] Cache Hit Ratio [mapper.UserMapper]: 0.5 User [id=1, name=小明, sex=男, age=21]
|
在关闭第一个sqlSession
时,查询的信息会保存到二级缓存中,重新获取sqlSession
,再次执行相同的查询时,由于二级缓存中已经有该数据,所以不需要再次执行sql
语句,而是直接从二级缓存中返回数据.
按id删除DeleteUserTest.java
/MyATwoLevelCacheTest/src/test/DeleteUserTest.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package test;
import java.util.List; import org.apache.ibatis.session.SqlSession; import domain.User; import fractory.SqlSessionFactoryTools; import mapper.UserMapper;
public class DeleteUserTest { public static void main(String[] args) { SqlSession sqlSession = null; try { sqlSession = SqlSessionFactoryTools.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> users = userMapper.selectAllUsers(); users.forEach(user -> System.out.println(" " + user)); System.out.println("----------------------------------------"); sqlSession.close(); System.out.println("----------------------------------------"); sqlSession = SqlSessionFactoryTools.getSqlSession(); userMapper = sqlSession.getMapper(UserMapper.class); users = userMapper.selectAllUsers(); users.forEach(user -> System.out.println(" " + user)); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if (sqlSession != null) sqlSession.close(); }
} }
|
运行效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| DEBUG [main] Cache Hit Ratio [mapper.UserMapper]: 0.0 DEBUG [main] ==> Preparing: select * from tb_user DEBUG [main] ==> Parameters: DEBUG [main] <== Total: 5 User [id=1, name=小明, sex=男, age=21] User [id=2, name=小王, sex=男, age=22] User [id=3, name=小丽, sex=女, age=18] User [id=4, name=小芳, sex=女, age=18] User [id=5, name=小王, sex=男, age=22] ---------------------------------------- ---------------------------------------- DEBUG [main] Cache Hit Ratio [mapper.UserMapper]: 0.5 User [id=1, name=小明, sex=男, age=21] User [id=2, name=小王, sex=男, age=22] User [id=3, name=小丽, sex=女, age=18] User [id=4, name=小芳, sex=女, age=18] User [id=5, name=小王, sex=男, age=22]
|
测试并没有执行删除语句,第二次查询时从二级缓存从返回数据.
取消删除语句的注释:
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 获取mapper接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAllUsers();
users.forEach(user-> System.out.println(user));
System.out.println("----------------------------------------");
userMapper.deleteUserById(users.get(0).getId());
sqlSession.commit();
sqlSession.close();
System.out.println("----------------------------------------");
// 再次加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 再次获取mapper接口代理对象
userMapper = sqlSession.getMapper(UserMapper.class);
users = userMapper.selectAllUsers();
users.forEach(user-> System.out.println(user));
再次执行,运行效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| DEBUG [main] Cache Hit Ratio [mapper.UserMapper]: 0.0 DEBUG [main] ==> Preparing: select * from tb_user DEBUG [main] ==> Parameters: DEBUG [main] <== Total: 5 User [id=1, name=小明, sex=男, age=21] User [id=2, name=小王, sex=男, age=22] User [id=3, name=小丽, sex=女, age=18] User [id=4, name=小芳, sex=女, age=18] User [id=5, name=小王, sex=男, age=22] ---------------------------------------- DEBUG [main] ==> Preparing: delete from tb_user where id=? DEBUG [main] ==> Parameters: 1(Integer) DEBUG [main] <== Updates: 1 ---------------------------------------- DEBUG [main] Cache Hit Ratio [mapper.UserMapper]: 0.0 DEBUG [main] ==> Preparing: select * from tb_user DEBUG [main] ==> Parameters: DEBUG [main] <== Total: 4 User [id=2, name=小王, sex=男, age=22] User [id=3, name=小丽, sex=女, age=18] User [id=4, name=小芳, sex=女, age=18] User [id=5, name=小王, sex=男, age=22]
|
DML语句会清空缓存
DML
语句(insert
,update
,delete
)会清空缓存,所以第二次查询时缓存中没有信息,需要再次执行SQL
语句从数据库中查询信息.