亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

Mybatis一級緩存項目實戰教程

標簽:
Java SSM 數據庫
概述

本文深入探讨了Mybatis一级缓存的工作原理和应用场景,通过项目实战详细讲解了如何在实际项目中利用Mybatis一级缓存来提高查询性能。文章介绍了开启和关闭一级缓存的方法,并提供了具体的代码示例,帮助读者更好地理解和实现Mybatis一级缓存项目实战。

Mybatis缓存简介

Mybatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。通过 Mybatis 可以将 Java 对象和数据库记录进行映射,从而简化了数据访问层的操作。Mybatis 提供了两种级别的缓存:一级缓存和二级缓存。

Mybatis缓存机制概述

Mybatis 缓存机制旨在减少数据库访问的次数,提高应用程序的性能。一级缓存是 Session 级别的缓存,当一个 Session 执行查询时,会将查询结果存储到 Session 的缓存中,下次查询相同的数据时,直接从缓存中读取,而不需要再次查询数据库。二级缓存则是整个应用级别的缓存,多个 Session 可以共享二级缓存中的数据。

Mybatis缓存的作用和意义

缓存机制有助于提高应用程序的响应速度,减少数据库的负担。通过缓存,可以将频繁访问的数据存储在内存中,避免每次请求都访问数据库,从而提高了系统的性能和可用性。此外,缓存机制还可以减少数据库的并发负载,提高系统的整体吞吐量。

Mybatis一级缓存详解
一级缓存的工作原理

一级缓存是 Mybatis 的默认缓存,位于 SqlSession 中,当一个 SqlSession 执行查询时,会将查询结果存储到缓存中。下次相同的查询请求时,如果缓存中存在相同的数据,则直接从缓存中读取,而不需要再次查询数据库。

一级缓存的工作流程如下:

  1. 当应用程序通过 SqlSession 执行查询时,SqlSession 会检查缓存中是否存在相同的数据。
  2. 如果缓存中存在相同的数据,则直接返回。
  3. 如果缓存中不存在相同的数据,则执行查询请求,将查询结果存储到缓存中。
  4. 当 SqlSession 被关闭时,缓存中的数据会被清除。
一级缓存的作用范围和生命周期

一级缓存的作用范围是 SqlSession。当同一个 SqlSession 执行相同的查询时,可以复用缓存中的数据。

一级缓存的生命周期与 SqlSession 相同。当 SqlSession 被关闭时,缓存中的数据会被清除。

Mybatis一级缓存的使用
开启和关闭一级缓存的配置方法

Mybatis 的一级缓存默认是开启的,可以通过配置文件进行关闭。

在 Mybatis 的配置文件 mybatis-config.xml 中,可以通过配置 <setting> 标签来关闭一级缓存:

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

通过设置 cacheEnabledfalse,可以关闭 Mybatis 的一级缓存。但一般情况下不需要关闭一级缓存,因为缓存机制可以显著提高应用程序的性能。

示例代码演示一级缓存的使用

接下来通过一个简单的示例来演示如何使用 Mybatis 的一级缓存。

假设有一个 User 表,包含 idname 两个字段:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

首先创建 User 实体类:

public class User {
    private int id;
    private String name;

    // 省略 getter 和 setter 方法
}

然后创建 UserMapper 接口:

public interface UserMapper {
    List<User> selectAllUsers();
}

实现 selectAllUsers 方法:

public class UserMapperImpl extends BaseMapper<User> implements UserMapper {
    @Override
    public List<User> selectAllUsers() {
        return sqlSession.selectList("selectAllUsers");
    }
}

selectAllUsers 方法对应的 SQL 映射文件:

<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectAllUsers" resultType="com.example.model.User">
        SELECT id, name FROM user
    </select>
</mapper>

接下来编写测试代码演示一级缓存的使用:

public class CacheTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        // 第一次查询
        List<User> users1 = userMapper.selectAllUsers();
        System.out.println("第一次查询结果: " + users1);

        // 第二次查询
        List<User> users2 = userMapper.selectAllUsers();
        System.out.println("第二次查询结果: " + users2);

        sqlSession.close();
    }
}

输出结果:

第一次查询结果: [User{id=1, name='Tom'}, User{id=2, name='Jerry'}]
第二次查询结果: [User{id=1, name='Tom'}, User{id=2, name='Jerry'}]

从输出结果可以看到,第二次查询时直接从缓存中读取了数据,而没有再次查询数据库。

Mybatis一级缓存的注意事项
一级缓存的清除时机

当 SqlSession 被关闭时,一级缓存中的数据会被清除。此外,在以下情况下,缓存中的数据也会被清除:

  • 当调用 SqlSession.clearCache() 方法时,会清除当前 SqlSession 中的所有缓存。
  • 当执行插入、更新或删除操作时,缓存中的数据会被清除,因为这些操作可能会改变数据库中的数据。
避免缓存带来的问题

虽然缓存可以提高应用程序的性能,但也可能会带来一些问题。例如,当数据库中的数据发生变化时,缓存中的数据可能已经过时。为了避免这种问题,可以采取以下措施:

  • 定期刷新缓存,确保缓存中的数据是最新的。
  • 在执行插入、更新或删除操作后,手动清除缓存,以确保缓存中的数据与数据库中的数据一致。
示例代码

手动清除缓存

public class CacheTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        // 第一次查询
        List<User> users1 = userMapper.selectAllUsers();
        System.out.println("第一次查询结果: " + users1);

        // 执行插入操作
        User newUser = new User();
        newUser.setId(3);
        newUser.setName("Alice");
        sqlSession.insert("insertUser", newUser);

        // 手动清除缓存
        sqlSession.clearCache();

        // 第二次查询
        List<User> users2 = userMapper.selectAllUsers();
        System.out.println("第二次查询结果: " + users2);

        sqlSession.close();
    }
}

定期刷新缓存

public class CacheTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        // 第一次查询
        List<User> users1 = userMapper.selectAllUsers();
        System.out.println("第一次查询结果: " + users1);

        // 执行插入操作
        User newUser = new User();
        newUser.setId(3);
        newUser.setName("Alice");
        sqlSession.insert("insertUser", newUser);

        // 定期刷新缓存
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        executor.scheduleAtFixedRate(() -> sqlSession.clearCache(), 0, 60, TimeUnit.SECONDS);

        // 第二次查询
        List<User> users2 = userMapper.selectAllUsers();
        System.out.println("第二次查询结果: " + users2);

        executor.shutdown();
        sqlSession.close();
    }
}
Mybatis一级缓存项目实战
实战项目需求分析

假设有一个电子商务网站,需要频繁查询商品信息。为了提高查询性能,可以使用 Mybatis 的一级缓存来缓存商品信息。

项目中涉及的实体类为 Product

public class Product {
    private int id;
    private String name;
    private double price;

    // 省略 getter 和 setter 方法
}
项目中一级缓存的实现步骤
  1. 创建 ProductMapper 接口:
public interface ProductMapper {
    List<Product> selectAllProducts();
}
  1. 实现 selectAllProducts 方法:
public class ProductMapperImpl extends BaseMapper<Product> implements ProductMapper {
    @Override
    public List<Product> selectAllProducts() {
        return sqlSession.selectList("selectAllProducts");
    }
}
  1. 编写 SQL 映射文件:
<mapper namespace="com.example.mapper.ProductMapper">
    <select id="selectAllProducts" resultType="com.example.model.Product">
        SELECT id, name, price FROM product
    </select>
</mapper>
  1. 编写测试代码:
public class CacheTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        ProductMapper productMapper = sqlSession.getMapper(ProductMapper.class);

        // 第一次查询
        List<Product> products1 = productMapper.selectAllProducts();
        System.out.println("第一次查询结果: " + products1);

        // 第二次查询
        List<Product> products2 = productMapper.selectAllProducts();
        System.out.println("第二次查询结果: " + products2);

        sqlSession.close();
    }
}

输出结果:

第一次查询结果: [Product{id=1, name='Product1', price=10.0}, Product{id=2, name='Product2', price=20.0}]
第二次查询结果: [Product{id=1, name='Product1', price=10.0}, Product{id=2, name='Product2', price=20.0}]
项目代码示例

完整的项目代码示例如下:

Product 实体类

public class Product {
    private int id;
    private String name;
    private double price;

    // getter 和 setter 方法
}

ProductMapper 接口

public interface ProductMapper {
    List<Product> selectAllProducts();
}

ProductMapperImpl 实现类

public class ProductMapperImpl extends BaseMapper<Product> implements ProductMapper {
    @Override
    public List<Product> selectAllProducts() {
        return sqlSession.selectList("selectAllProducts");
    }
}

SQL 映射文件

<mapper namespace="com.example.mapper.ProductMapper">
    <select id="selectAllProducts" resultType="com.example.model.Product">
        SELECT id, name, price FROM product
    </select>
</mapper>

测试代码

public class CacheTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        ProductMapper productMapper = sqlSession.getMapper(ProductMapper.class);

        // 第一次查询
        List<Product> products1 = productMapper.selectAllProducts();
        System.out.println("第一次查询结果: " + products1);

        // 第二次查询
        List<Product> products2 = productMapper.selectAllProducts();
        System.out.println("第二次查询结果: " + products2);

        sqlSession.close();
    }
}

MybatisUtil.getSqlSession() 方法的具体实现

public class MybatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            // 配置文件路径
            String resource = "mybatis-config.xml";
            // 读取配置文件
            Reader reader = Resources.getResourceAsReader(resource);
            // 创建 SqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

BaseMapper 类的具体实现

public abstract class BaseMapper<T> {
    protected SqlSession sqlSession;

    public BaseMapper(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }
}
Mybatis一级缓存调试和优化
调试一级缓存的方法

调试 Mybatis 的一级缓存可以通过以下几种方法:

  1. 打印缓存信息:可以在 mybatis-config.xml 文件中配置 logImplSTDOUT_LOGGING,通过日志输出缓存的相关信息。
  2. 使用 Mybatis 的调试工具:例如 Mybatis 的插件 mybatis-plus 提供了一些调试工具,可以方便地查看缓存状态。
  3. 手动清除缓存:在测试代码中调用 SqlSession.clearCache() 方法,观察缓存是否被清除。
优化一级缓存的策略

优化 Mybatis 的一级缓存可以通过以下几种策略:

  1. 合理设置缓存大小:根据应用程序的需求,合理设置缓存的大小,避免缓存过大导致内存溢出。
  2. 定期刷新缓存:定期刷新缓存,确保缓存中的数据是最新的。
  3. 手动清除缓存:在执行插入、更新或删除操作后,手动清除缓存,以确保缓存中的数据与数据库中的数据一致。
  4. 使用二级缓存:如果一级缓存的性能仍不能满足需求,可以考虑使用二级缓存,多个 SqlSession 可以共享二级缓存中的数据。
點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
全棧工程師
手記
粉絲
233
獲贊與收藏
1006

關注作者,訂閱最新文章

閱讀免費教程

  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消