MyBatis学习手记(二)MyBatis缓存机制

MyBatis学习手记二

前:MyBatis官方学习(中文)文档 http://mybatis.github.io/mybatis-3/zh/index.html

一,首先,要使用MyBatis必须使用官方提供的MyBatis的JAR包

             链接:https://github.com/mybatis/mybatis-3/releases

这里使用的数据库是MySQL,所以还需要Mysql的驱动包、

二,看MyBatis官方介绍,说MyBatis支持一级缓存,二级缓存。这里才是我真正要学习MyBatis的原因来源。

要知道,如果在项目中,在Dao层中使用了缓存机制的话,你的数据库压力将会大大优化。你的程序的响应速度也将大大提升。

在MyBatis中,一级缓存其实已经默认打开了、

public static void main(String[] args) throws Exception
{
    SqlSession session = sqlSessionFactory.openSession();

    UserMapper userMapper = session.getMapper(UserMapper.class);

    User user = userMapper.selectUserById(1);
    User user2 = userMapper.selectUserById(1);
    
    System.out.println(user.getName());
    System.out.println(user2.getName());
    
    session.close();
}

这里,我们只新建了一个SqlSession,然后实例化一个UserMapper 查询两次。

然后我们可以看一下控制台打印的BUG

DEBUG [main] - Logging initialized using ‘org.apache.ibatis.logging.log4j.Log4jImpl‘ adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Openning JDBC Connection
DEBUG [main] - Created connection 27187756.
DEBUG [main] - ooo Using Connection [[email protected]]
DEBUG [main] - ==>  Preparing: select * from user where id = ? 
DEBUG [main] - ==> Parameters: 1(Integer)
xiaolei
xiaolei
DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
DEBUG [main] - Closing JDBC Connection [[email protected]]
DEBUG [main] - Returned connection 27187756 to pool.

从这里我就能看见,虽然我们在代码中执行了两次查询,可是真正从数据库中获取数据的操作,却只有一次。

Preparing: select * from user where id = ?

三、也就是说,这里一级缓存,我们可以不用去考虑。然后我们重点考虑一下二级缓存

通过查询资料,我发现,二级缓存其实也不是那么复杂、只需要在配置文件中配置一下,就OK了、

MyBatis-Config.xml

<?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>
    
    <settings>
	<setting name="cacheEnabled" value="true"/>
    </settings>
    
    <environments default="development">
        <environment id="development">
        <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
            <property name="username" value="root"/>
            <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.xcode.beens.mapperInterfaces.UserMapper"/>
    </mappers>
</configuration>

我们发现。这个配置文件与之前的配置文件,多了这么个东西

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

好吧,当我发现只要配置这么一段话的时候,劳资真想说:‘吓死宝宝了‘

然后我再继续测试,发现并没什么区别。然后有些操作还会报错

org.apache.ibatis.cache.CacheException: Error serializing object.  
Cause: java.io.NotSerializableException:

当出现这个异常的时候,我就知道,并没有那么简单。

然后我查阅资料,发现,原来是我的Been有问题,原来要实现二级缓存,就必须实现可序列化接口:java.io.Serializable

User.java实现一下这个接口:

package com.xcode.beens;

import java.io.Serializable;

public class User implements Serializable
{
	private static final long serialVersionUID = 8942594370466951584L;
	private int id;
	private String name;
	private String sex;
	private String address;
	public int getId()
	{
		return id;
	}
	public void setId(int id)
	{
		this.id = id;
	}
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public String getSex()
	{
		return sex;
	}
	public void setSex(String sex)
	{
		this.sex = sex;
	}
	public String getAddress()
	{
		return address;
	}
	public void setAddress(String address)
	{
		this.address = address;
	}
}

当一切完成之后,再测试:

public static void main(String[] args) throws Exception
	{
		SqlSession session = sqlSessionFactory.openSession();
		SqlSession session2 = sqlSessionFactory.openSession();

		UserMapper userMapper = session.getMapper(UserMapper.class);
		UserMapper userMapper2 = session2.getMapper(UserMapper.class);

		User user = userMapper.selectUserById(1);

		session.commit();//这里一定要提交一下,否则也会查询两次

		User user2 = userMapper2.selectUserById(1);

		System.out.println(user.getName());
		System.out.println(user2.getName());

		session.close();
		session2.close();
	}

这段代码中我们可以看到,我在这里实例化了两个 SqlSession 然后不同的SqlSession实例化了不同的 UserMapper,

两个UserMapper执行同样的操作,都是对数据库进行查询。,这时我们看一下控制台日志:

DEBUG [main] - Logging initialized using ‘org.apache.ibatis.logging.log4j.Log4jImpl‘ adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Cache Hit Ratio [com.xcode.beens.mapperInterfaces.UserMapper]: 0.0
DEBUG [main] - Openning JDBC Connection
DEBUG [main] - Created connection 12644844.
DEBUG [main] - ooo Using Connection [[email protected]]
DEBUG [main] - ==>  Preparing: select * from user where id = ? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - Cache Hit Ratio [com.xcode.beens.mapperInterfaces.UserMapper]: 0.5
xiaolei
xiaolei
DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
DEBUG [main] - Closing JDBC Connection [[email protected]]
DEBUG [main] - Returned connection 12644844 to pool.

我们这回看见,虽然我们代码里查询了两次,可是真正去数据库中查询,我们却只查询了一次,也就是说,我们第二次是读的缓存。

注:在之前我用了注解的方式,发现缓存根本没有起作用,然后我查了一下,没有找到使用注解就使用二级缓存的方式

也就是说,这里必须使用UserMapper.xml配置文件配置,才能使用二级缓存。

MyBatis-Config.xml  需要修改为:

<?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>
    
    <settings>
	<setting name="cacheEnabled" value="true"/>
    </settings>
	<!-- 这里需要注意,这个typeAliases不能放在 environments 这个节点的下面,否则会报错 -->
    <typeAliases> 
        <typeAlias alias="User" type="com.xcode.beens.User"/> 
    </typeAliases> 
    
    <environments default="development">
        <environment id="development">
        <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
            <property name="username" value="root"/>
            <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/xcode/beens/mapperInterfaces/UserMapper.xml"/>
    </mappers>
</configuration>

我们注意到,修改的地方就是

<mappers>
       <mapper resource="com/xcode/beens/mapperInterfaces/UserMapper.xml"/>
</mappers>

然后我们在 com.xcode.beens.mapperInterfaces 包下新建 UserMapper.xml 配置文件

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE mapper 
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<mapper namespace="com.xcode.beens.mapperInterfaces.UserMapper"> 
    <cache />
    <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 -->
    <select id="selectUserById" parameterType="int" resultType="User">
            select * from user where id = #{id}
    </select>
    
    <select id="selectUsersByName" parameterType="string" resultMap="resultListUser">
           select * from user where name = #{name}
    </select>
    <!-- 为了返回list 类型而定义的returnMap -->
    <resultMap type="User" id="resultListUser">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="sex" property="sex" />
        <result column="address" property="address" />
    </resultMap>
    
    <insert id="insertUser" parameterType="User">
           INSERT INTO `user` (`name`, `sex`, `address`) VALUES (#{name},#{sex},#{address})
    </insert>
    
    <delete id="deleteUserByID" parameterType="int">
           delete from user where id = #{id}
    </delete>
    
</mapper>

我们注意一行:

<mapper namespace="com.xcode.beens.mapperInterfaces.UserMapper">

namespace配置的就是Mapper接口的 全限定名。

再我们修改一下 UserMapper.java

package com.xcode.beens.mapperInterfaces;

import java.util.List;
import com.xcode.beens.User;

public interface UserMapper
{
	public User selectUserById(int id);
	public List<User> selectUsersByName(String name);
	public void insertUser(User user);
	public void deleteUserByID(int id);
}

我们这里将前面所有的注解都删了,注解的SQL语句配置到UserMapper.xml文件中了。

好了,收工!再执行一下刚才的 Main , 二级缓存使用成功!

这里很多都没有详细讲,比如那个Mapper配置文件。以及返回结果集是多条的时候,怎么转换成List的。我也是刚学,写博客只是为了记录下来以便自己以后忘记了,能迅速拿起来。

时间: 2024-10-10 14:27:55

MyBatis学习手记(二)MyBatis缓存机制的相关文章

Mybatis学习记录(二)--Mybatis开发DAO方式

mybatis开发dao的方法通常用两种,一种是传统DAO的方法,一种是基于mapper代理的方法,下面学习这两种开发模式. 写dao之前应该要对SqlSession有一个更加细致的了解 一.mybatis的SqlSession使用范围 SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产

MyBatis学习笔记二:MyBatis生产中使用环境搭建

这里是在上一个环境的基础上修改的,这里就不在给出所有的配置,只给出哪里修改的配置 1.修改POJO对象为注解方式 2.创建Dao层接口 package com.orange.dao; import com.orange.model.Person; public interface PersonDao { // 这里的返回值和方法名必须和PersonMapper.xml中定义的执行语句的id一致 public Person selectPerson(); } 3.修改PersonMapper.xm

mybatis学习笔记二mybatis结合spring mvc实现(用户登录,数据查询)

接着上次的来,我做了一个用户登录的例子 UserController: package com.yihaomen.controller; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.spring

MyBatis学习总结(七)——Mybatis缓存(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(七)--Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空. 2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,Hash

【转】MyBatis学习总结(七)——Mybatis缓存

[转]MyBatis学习总结(七)——Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空. 2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 M

mybatis学习笔记(13)-查询缓存之二级缓存

mybatis学习笔记(13)-查询缓存之二级缓存 mybatis学习笔记13-查询缓存之二级缓存 二级缓存原理 开启二级缓存 调用pojo类实现序列化接口 测试方法 useCache配置 刷新缓存就是清空缓存 应用场景和局限性 本文主要讲mybatis的二级缓存,二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的. 二级缓存原理 首先开启mybatis的二级缓存. sqlS

MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(二)--使用MyBatis对表执行CRUD操作 上一篇博文MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对users表执行CRUD操作.本文中使用到的测试环境是上一篇博文中的测试环境. 一.使用MyBatis对表执行CRUD操作--基于XML的实现 1.定义sql映射xml文件 userMa

mybatis学习笔记(14)-查询缓存之中的一个级缓存

mybatis学习笔记(14)-查询缓存之中的一个级缓存 mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 本文主要讲mybatis的一级缓存.一级缓存是SqlSession级别的缓存. 查询缓存 mybatis提供查询缓存.用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时须要构造sqlSession对象,在对象中有一个数据结构(HashMa

MyBatis学习总结(一)——MyBatis快速入门(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(一)--MyBatis快速入门 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 二.mybatis快速入门 2.1.准备