MyBatis一级缓存实战

一 领域模型

package org.fkit.domain;
import java.io.Serializable;
/**
*
* 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`)
)
*/
public class User implements Serializable{
     
     private static final long serialVersionUID = 1L;
     
     private Integer id;
     private String name;
     private String sex;
     private Integer age;
     
     public User() {
           super();
           // TODO Auto-generated constructor stub
     }
     
     public User( String name, String sex, Integer age) {
           super();
           this.name = name;
           this.sex = sex;
           this.age = age;
     }
     public Integer getId() {
           return id;
     }
     public void setId(Integer 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 Integer getAge() {
           return age;
     }
     public void setAge(Integer age) {
           this.age = age;
     }
     @Override
     public String toString() {
           return "User [id=" + id + ", name=" + name + ", sex="  + sex + ", age="
                     + age + "]";
     }
     
     
}

二 会话工厂

package org.fkit.factory;

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 FKSqlSessionFactory {
    
    private static SqlSessionFactory sqlSessionFactory = null;
    
    // 初始化创建SqlSessionFactory对象
    static{
        try (// 读取mybatis-config.xml文件
                InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            ){
            sqlSessionFactory = new SqlSessionFactoryBuilder()
                    .build(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 获取SqlSession对象的静态方法
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }

    // 获取SqlSessionFactory的静态方法
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

}

三 mapper

1 UserMapper

package org.fkit.mapper;

import java.util.List;
import org.fkit.domain.User;

public interface UserMapper {
    
    // 根据id查询User
    User selectUserById(Integer id);
    
    // 查询所有User
    List<User> selectAllUser();
    
    // 根据id删除User
    void deleteUserById(Integer id);

}

2 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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.UserMapper">
     
  <!-- 根据id查询User -->
  <select id="selectUserById" parameterType="int"
  resultType="org.fkit.domain.User">
      SELECT * FROM TB_USER WHERE id = #{id}
  </select>
  
  <!-- 查询所有User -->
  <select id="selectAllUser" resultType="org.fkit.domain.User">
      SELECT * FROM TB_USER
  </select>
  
  <!-- 根据id删除User -->
  <delete id="deleteUserById" parameterType="int">
      DELETE FROM TB_USER WHERE id = #{id}
  </delete>
  
</mapper>

四 配置文件

1 db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis
username=root
password=123456

2 log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">  
<log4j:configuration  xmlns:log4j="http://jakarta.apache.org/log4j/">  
    <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="org.fkit.mapper">  
        <level value="DEBUG" />  
    </logger>
    <root>  
        <level value="ERROR" />  
        <appender-ref ref="STDOUT" />  
    </root>  
</log4j:configuration>

3 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">
  <!--  XML 配置文件包含对 MyBatis 系统的核心设置 -->
<configuration>
     <properties resource="db.properties"/>
     <!-- 指定 MyBatis 所用日志的具体实现 -->
     <settings>
           <setting name="logImpl" value="LOG4J"/>
     </settings>
     <environments default="mysql">
     <!-- 环境配置,即连接的数据库。 -->
    <environment id="mysql">
    <!--  指定事务管理类型,type="JDBC"指直接简单使用了JDBC的提交和回滚设置 -->
      <transactionManager type="JDBC"/>
      <!--  dataSource指数据源配置,POOLED是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告诉了MyBatis去哪里找持久化类的映射文件 -->
  <mappers>
      <mapper resource="org/fkit/mapper/UserMapper.xml"/>
  </mappers>
</configuration>

五 测试

package org.fkit.test;

import org.apache.ibatis.session.SqlSession;
import org.fkit.domain.User;
import org.fkit.factory.FKSqlSessionFactory;
import org.fkit.mapper.UserMapper;

public class OneLevelCacheTest {

    public static void main(String[] args)  {

        // 定义SqlSession变量
        SqlSession sqlSession = null;
        try {
            // 创建SqlSession实例
            sqlSession = FKSqlSessionFactory.getSqlSession();
            OneLevelCacheTest t = new OneLevelCacheTest();

//            t.testCache1(sqlSession);
//            t.testCache2(sqlSession);
//            t.testCache3(sqlSession);
            t.testCache4();
            
            // 提交事务
            sqlSession.commit();
        } catch (Exception e) {
            // 回滚事务
            sqlSession.rollback();
            e.printStackTrace();
        }finally {
            // 关闭SqlSession
            if(sqlSession != null)
                sqlSession.close();
        }
    }
    
     /*
      * 一级缓存: 也就Session级的缓存(默认开启)
      */
    public void testCache1 (SqlSession sqlSession){
        // 获得UserMapping对象
        UserMapper um = sqlSession.getMapper(UserMapper.class);
        // 查询id为1的User对象,会执行select语句
        User user = um.selectUserById(1);
        System.out.println(user);
        // 再次查询id为1的User对象,因为是同一个SqlSession,所以会从之前的一级缓存中查找数据
        User user2 = um.selectUserById(1);
        System.out.println(user2);
    }
    
    // 测试一级缓存执行DML语句并提交
    public void testCache2 (SqlSession sqlSession){
        // 获得UserMapping对象
        UserMapper um = sqlSession.getMapper(UserMapper.class);
        // 查询id为1的User对象,会执行select语句
        User user = um.selectUserById(1);
        System.out.println(user);
        // 执行delete操作
        um.deleteUserById(5);
        // commit提交
        sqlSession.commit();
        // 再次查询id为1的User对象,因为DML操作会清空SqlSession缓存,所以会再次执行select语句
        User user2 = um.selectUserById(1);
        System.out.println(user2);
    }
    
    // 测试一级缓存clearCache
    public void testCache3 (SqlSession sqlSession){
        // 获得UserMapping对象
        UserMapper um = sqlSession.getMapper(UserMapper.class);
        // 查询id为1的User对象,会执行select语句
        User user = um.selectUserById(1);
        System.out.println(user);
        // 清空一级缓存
        sqlSession.clearCache();
        // 再次获得UserMapping对象
        um = sqlSession.getMapper(UserMapper.class);
        // 再次访问,因为SqlSession一级缓存已经清空,所以会再次执行select语句
        User user2 = um.selectUserById(1);
        System.out.println(user2);
    }
    
    // 测试一级缓存close
    public void testCache4 (){
        // 使用工厂类获得SqlSession对象
        SqlSession sqlSession = FKSqlSessionFactory.getSqlSession();
        // 获得UserMapping对象
        UserMapper um = sqlSession.getMapper(UserMapper.class);
        // 查询id为1的User对象,会执行select语句
        User user = um.selectUserById(1);
        System.out.println(user);
        // 关闭一级缓存
        sqlSession.close();
        // 再次访问,重新获取一级缓存,然后才能查找数据,否则会抛出异常
        SqlSession sqlSession2 = FKSqlSessionFactory.getSqlSession();
        // 再次获得UserMapping对象
        um = sqlSession2.getMapper(UserMapper.class);
        // 再次访问,因为现在使用的是一个新的SqlSession对象,所以会再次执行select语句
        User user2 = um.selectUserById(1);
        System.out.println(user2);
        // 关闭SqlSession对象
        sqlSession2.close();
    }

}

六 测试结果

1 testCache1

DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]
User [id=1, name=cakin, sex=男, age=18]

2 testCache2

DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]
DEBUG [main] ==>  Preparing: DELETE FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 5(Integer)
DEBUG [main] <==    Updates: 0
DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]

3 testCache3

DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]
DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]

4 testCache4

DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]
DEBUG [main] ==>  Preparing: SELECT * FROM TB_USER WHERE id = ?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <==      Total: 1
User [id=1, name=cakin, sex=男, age=18]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值