直播电商源码,一级缓存机制可提高查询效率

直播电商源码,一级缓存机制可提高查询效率

一级缓存机制展示

在Mybatis中如果多次执行完全相同的SQL语句时,Mybatis提供了一级缓存机制用于提高查询效率。一级缓存是默认开启的,如果想要手动配置,需要在Mybatis配置文件中加入如下配置。

<settings>
    <setting name="localCacheScope" value="SESSION"/>
</settings>

其中localCacheScope可以配置为SESSION(默认)或者STATEMENT,含义如下所示。
SESSION:一级缓存在一个会话中生效。即在一个会话中的所有查询语句,均会共享同一份一级缓存,不同会话中的一级缓存不共享。
STATEMENT:一级缓存仅针对当前执行的SQL语句生效。当前执行的SQL语句执行完毕后,对应的一级缓存会被清空。
下面以一个例子对Mybatis的一级缓存机制进行演示和说明。首先开启日志打印,然后关闭二级缓存,并将一级缓存作用范围设置为SESSION,配置如下。

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING" />
    <setting name="cacheEnabled" value="false"/>
    <setting name="localCacheScope" value="SESSION"/>
</settings>

映射接口如下所示。

public interface BookMapper {

    Book selectBookById(int id);

}

映射文件如下所示。

<?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.mybatis.learn.dao.BookMapper">
    <resultMap id="bookResultMap" type="com.mybatis.learn.entity.Book">
        <result column="b_name" property="bookName"/>
        <result column="b_price" property="bookPrice"/>
    </resultMap>

    <select id="selectBookById" resultMap="bookResultMap">
        SELECT
        b.id, b.b_name, b.b_price
        FROM
        book b
        WHERE
        b.id=#{id}
    </select>
</mapper>

Mybatis的执行代码如下所示。

public class MybatisTest {

    public static void main(String[] args) throws Exception {
        String resource = "mybatis-config.xml";
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsStream(resource));
        SqlSession sqlSession = sqlSessionFactory.openSession(false);
        BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);

        System.out.println(bookMapper.selectBookById(1));
        System.out.println(bookMapper.selectBookById(1));
        System.out.println(bookMapper.selectBookById(1));
    }

}

在执行代码中,连续执行了三次查询操作,看一下日志打印,如下所示。

 

可以知道,只有第一次查询时和数据库进行了交互,后面两次查询均是从一级缓存中查询的数据。现在往映射接口和映射文件中加入更改数据的逻辑,如下所示。

public interface BookMapper {

    Book selectBookById(int id);
    // 根据id更改图书价格
    void updateBookPriceById(@Param("id") int id, @Param("bookPrice") float bookPrice);

}

 

<?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.mybatis.learn.dao.BookMapper">
    <resultMap id="bookResultMap" type="com.mybatis.learn.entity.Book">
        <result column="b_name" property="bookName"/>
        <result column="b_price" property="bookPrice"/>
    </resultMap>

    <select id="selectBookById" resultMap="bookResultMap">
        SELECT
        b.id, b.b_name, b.b_price
        FROM
        book b
        WHERE
        b.id=#{id}
    </select>

    <insert id="updateBookPriceById">
        UPDATE
        book
        SET
        b_price=#{bookPrice}
        WHERE
        id=#{id}
    </insert>
</mapper>

 

执行的操作为先执行一次查询操作,然后执行一次更新操作并提交事务,最后再执行一次查询操作,执行代码如下所示。

public class MybatisTest {

    public static void main(String[] args) throws Exception {
        String resource = "mybatis-config.xml";
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsStream(resource));
        SqlSession sqlSession = sqlSessionFactory.openSession(false);
        BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);

        System.out.println(bookMapper.selectBookById(1));

        System.out.println("Change database.");
        bookMapper.updateBookPriceById(1, 22.5f);
        sqlSession.commit();

        System.out.println(bookMapper.selectBookById(1));
    }

}

 

执行结果如下所示。

 

通过上述结果可以知道,在执行更新操作之后,再执行查询操作时,是直接从数据库查询的数据,并未使用一级缓存,即在一个会话中,对数据库的增,删,改操作,均会使一级缓存失效。

现在在执行代码中创建两个会话,先让会话1执行一次查询操作,然后让会话2执行一次更新操作并提交事务,最后让会话1再执行一次相同的查询。执行代码如下所示。

public class MybatisTest {

    public static void main(String[] args) throws Exception {
        String resource = "mybatis-config.xml";
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsStream(resource));
        SqlSession sqlSession1 = sqlSessionFactory.openSession(false);
        SqlSession sqlSession2 = sqlSessionFactory.openSession(false);
        BookMapper bookMapper1 = sqlSession1.getMapper(BookMapper.class);
        BookMapper bookMapper2 = sqlSession2.getMapper(BookMapper.class);

        System.out.println(bookMapper1.selectBookById(1));

        System.out.println("Change database.");
        bookMapper2.updateBookPriceById(1, 22.5f);
        sqlSession2.commit();

        System.out.println(bookMapper1.selectBookById(1));
    }

}

 

执行结果如下所示。

 

上述结果表明,会话1的第一次查询是直接查询的数据库,然后会话2执行了一次更新操作并提交了事务,此时数据库中id为1的图书的价格已经变更为了22.5,紧接着会话1又做了一次查询,但查询结果中的图书价格为20.5,说明会话1的第二次查询是从缓存获取的查询结果。所以在这里可以知道,Mybatis中每个会话均会维护一份一级缓存,不同会话之间的一级缓存各不影响。

在本小节最后,对Mybatis的一级缓存机制做一个总结,如下所示。

Mybatis的一级缓存默认开启,且默认作用范围为SESSION,即一级缓存在一个会话中生效,也可以通过配置将作用范围设置为STATEMENT,让一级缓存仅针对当前执行的SQL语句生效;
在同一个会话中,执行增,删,改操作会使本会话中的一级缓存失效;
不同会话持有不同的一级缓存,本会话内的操作不会影响其它会话内的一级缓存。

以上就是直播电商源码,一级缓存机制可提高查询效率, 更多内容欢迎关注之后的文章

posted @ 2025-05-10 09:35  云豹科技-苏凌霄  阅读(10)  评论(0)    收藏  举报