MyBatis延遲加載與多級緩存全解析
MyBatis延遲加載策略
在 MyBatis 中,延遲加載(Lazy Loading) 是一種按需加載數(shù)據(jù)的機制,指在查詢主對象時,不立即加載其關(guān)聯(lián)的子對象(或關(guān)聯(lián)數(shù)據(jù)),而是等到真正需要使用這些關(guān)聯(lián)數(shù)據(jù)時,才發(fā)起數(shù)據(jù)庫查詢?nèi)ゼ虞d。這種機制的核心目的是減少不必要的數(shù)據(jù)庫交互,提高系統(tǒng)性能,尤其適用于關(guān)聯(lián)關(guān)系復(fù)雜或關(guān)聯(lián)數(shù)據(jù)量大的場景。
延遲加載主要用于關(guān)聯(lián)查詢,即通過resultMap中 <association>(一對一)或 <collection>(一對多)配置的關(guān)聯(lián)對象。
立即加載和延遲加載的區(qū)別,使用一對多的環(huán)境舉例子。
立即加載:當(dāng)前查詢用戶的時候,默認(rèn)也把該用戶所擁有的帳戶信息查詢出來;
延遲加載:當(dāng)前查詢用戶的時候,沒有把該用戶所擁有的帳戶信息查詢出來,而是使用帳戶數(shù)據(jù)的時候,再去查詢賬戶的數(shù)據(jù)。
一對多示例
編寫 JavaBean
import java.io.Serializable;
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
// 添加用戶屬性
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}package com.qcby.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class User implements Serializable {
//主鍵
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 存儲所有的id
private List<Integer> ids;
// 一個用戶擁有多個賬戶(演示一對多查詢)
private List<Account> accounts;
// 一個用戶擁有多個角色(演示多對多查詢)
private List<Role> roles;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
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 List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", ids=" + ids +
", accounts=" + accounts +
", roles=" + roles +
'}';
}
}SqlMapConfig_lazy.xml 中開啟延遲加載(lazyLoadingEnabled),以及將積極加載(aggressive lazy loading)改為消極加載(按需加載)
<?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="lazyLoadingEnabled" value="true"/>
<!-- 將積極加載改為消極加載/按需加載 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 配置環(huán)境 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 加載映射的配置文件 -->
<mappers>
<mapper resource="mappers/AccountMapper.xml"/>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>在AccountMapper.java接口內(nèi)編寫方法
import com.qcby.domain.Account;
import java.util.List;
public interface AccountMapper {
public List<Account> findAccountAll();
public List<Account> findAccountAllLazy();
}編寫AccountMapper.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.qcby.mapper.AccountMapper">
<!--內(nèi)連接查詢-->
<select id="findAccountAll" resultMap="accountMap">
select a.*,u.username,u.sex from account as a, user as u where a.uid=u.id;
</select>
<!--配置resultMap標(biāo)簽 目的是進(jìn)行數(shù)據(jù)封裝-->
<resultMap id="accountMap" type="com.qcby.domain.Account">
<result property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<association property="user" javaType="com.qcby.domain.User">
<result property="username" column="username" />
<result property="sex" column="sex" />
</association>
</resultMap>
<!--延遲加載-->
<select id="findAccountAllLazy" resultMap="accountlazyMap">
SELECT * FROM account;
</select>
<resultMap id="accountlazyMap" type="com.qcby.domain.Account">
<result property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<!--配置多對一的延遲加載(Account關(guān)聯(lián)的user集合,對user屬性進(jìn)行數(shù)據(jù)封裝)-->
<association property="user" javaType="com.qcby.domain.User" column="uid" select="com.qcby.mapper.UserMapper.findById" fetchType="lazy"/>
</resultMap>
</mapper>在 resultMap 的關(guān)聯(lián)標(biāo)簽中配置延遲加載:
column=“uid” 即查詢user時需要傳遞的參數(shù),select=“com.qcby.mapper.UserMapper.findById” 指定加載user對象時要調(diào)用的SQL語句,fetchType 屬性是延遲加載的局部配置方式,lazy表示延遲加載、eager立即加載,fetchType="lazy"只有明確訪問關(guān)聯(lián)對象的屬性時才會觸發(fā)關(guān)聯(lián)對象的加載,進(jìn)一步減少不必要的數(shù)據(jù)庫查詢。
其中 UserMapper.findById 的查詢語句如下:

測試方法
import com.qcby.domain.Account;
import com.qcby.mapper.AccountMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserTest_lazy {
@Test
public void testfindRoleALL(){
try {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig_lazy.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
AccountMapper mapper = session.getMapper(AccountMapper.class);
List<Account> accounts = mapper.findAccountAll();
for (Account account : accounts) {
System.out.println(account);
System.out.println(account.getMoney());
System.out.println(account.getUser().getUsername());
System.out.println("==============");
}
//關(guān)閉資源
session.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 測試延遲加載的測試方法
*/
@Test
public void testfindAccountlazyALL(){
try {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig_lazy.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
AccountMapper mapper = session.getMapper(AccountMapper.class);
List<Account> list = mapper.findAccountAllLazy();
for (Account account : list) {
System.out.println(account.getMoney());
//System.out.println(account.getUser().getUsername());
System.out.println("=============================");
System.out.println("");
}
//關(guān)閉資源
session.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}實現(xiàn)效果:
運行 testfindRoleALL() 方法,立即加載,通過內(nèi)連接一次性查詢賬戶和關(guān)聯(lián)的用戶信息

運行 testfindAccountlazyALL() 方法,延遲加載,先查詢賬戶信息,當(dāng)需要用戶信息時再單獨查詢,減少不必要的數(shù)據(jù)庫交互
輸出 user.getUsername() 時,不會觸發(fā)關(guān)聯(lián)對象的加載,只執(zhí)行 SELECT * FROM account;

輸出 user.getAccounts().size() 時,第一步固定執(zhí)行查詢所有賬戶信息 SELECT * FROM account;,訪問到Account對象的user屬性觸發(fā)延遲加載,第二步執(zhí)行子查詢語句 select * from user where id = ?; ,其中?會被替換為傳入的column="uid"的具體賬戶的uid值

一對多示例
UserMapper.java 接口添加方法
import com.qcby.domain.User;
import java.util.List;
public interface UserMapper {
//一對多延遲加載查詢
public List<User> findUserAllLazy();
}UserMapper.xml 配置文件中添加
<!-- 一對多延遲加載 -->
<select id="findUserAllLazy" resultMap="UserAlllazy">
SELECT * FROM user;
</select>
<resultMap id="UserAlllazy" type="com.qcby.domain.User">
<result property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!-- 配置一對多的延遲加載(User關(guān)聯(lián)的accounts集合,對accounts屬性進(jìn)行數(shù)據(jù)封裝)-->
<collection property="accounts" ofType="com.qcby.domain.Account" column="id" select="com.qcby.mapper.AccountMapper.findAccountById" fetchType="lazy"/>
</resultMap>AccountMapper.xml 配置文件中添加
<!-- 根據(jù)用戶id(uid)查詢該用戶的所有賬戶 -->
<select id="findAccountById" parameterType="int" resultType="com.qcby.domain.Account">
SELECT * FROM account where uid=#{uid};
</select>SqlMapConfig_lazy.xml 配置文件內(nèi)容不變
<?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="lazyLoadingEnabled" value="true"/>
<!-- 將積極加載改為消極加載/按需加載 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 配置環(huán)境 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 加載映射的配置文件 -->
<mappers>
<mapper resource="mappers/AccountMapper.xml"/>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>測試方法
import com.qcby.domain.Account;
import com.qcby.domain.User;
import com.qcby.mapper.AccountMapper;
import com.qcby.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserTest_lazy {
@Test
public void testfindUserlazyALL(){
try {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig_lazy.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.findUserAllLazy();
for (User user : list) {
System.out.println(user.getUsername());
//System.out.println(user.getAccounts().size());
System.out.println("=============================");
System.out.println("");
}
//關(guān)閉資源
session.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}實現(xiàn)效果:
輸出 user.getUsername() 時,不會觸發(fā)關(guān)聯(lián)對象的加載,只執(zhí)行 SELECT * FROM user;

輸出 user.getAccounts().size() 時,第一步固定執(zhí)行查詢所有用戶信息 SELECT * FROM user;,訪問到User對象的accounts屬性觸發(fā)延遲加載,第二步執(zhí)行子查詢語句 SELECT * FROM account where uid = ?; ,其中?會被替換為傳入的column="id"的具體用戶的id值

MyBatis框架的緩存
緩存是指在計算系統(tǒng)中,通過特定的高速存儲介質(zhì)臨時存儲數(shù)據(jù)源中頻繁訪問的數(shù)據(jù)副本,以實現(xiàn)數(shù)據(jù)快速復(fù)用的機制。其核心原理是利用高速存儲介質(zhì)與數(shù)據(jù)源之間的訪問速度差異,當(dāng)數(shù)據(jù)請求發(fā)生時,優(yōu)先從緩存中查詢目標(biāo)數(shù)據(jù):若緩存中存在該數(shù)據(jù),則直接返回緩存副本,避免對原始數(shù)據(jù)源的訪問;若緩存中不存在該數(shù)據(jù),則從數(shù)據(jù)源獲取數(shù)據(jù)并同步至緩存,為后續(xù)可能的重復(fù)請求提供基礎(chǔ)。
這種機制通過縮短數(shù)據(jù)訪問路徑、降低對低速數(shù)據(jù)源的依賴,有效提升了系統(tǒng)響應(yīng)速度與整體吞吐量,是計算機領(lǐng)域優(yōu)化數(shù)據(jù)訪問性能的核心技術(shù)之一。
一級緩存
MyBatis 的一級緩存,官方稱其為本地緩存(Local Cache),是框架默認(rèn)啟用且無需額外配置的會話級緩存機制,其作用域嚴(yán)格限定在單個 SqlSession 實例的生命周期內(nèi)。在實現(xiàn)層面,每個 SqlSession 對象內(nèi)部維護(hù)著一個基于 Map 的鍵值對集合,專門用于存儲緩存數(shù)據(jù)。
其工作流程遵循緩存優(yōu)先原則:當(dāng)通過當(dāng)前 SqlSession 執(zhí)行查詢操作時,MyBatis 會先在一級緩存中進(jìn)行檢索,若緩存中存在對應(yīng)數(shù)據(jù),則直接返回該緩存副本,無需與數(shù)據(jù)庫交互;若緩存中不存在目標(biāo)數(shù)據(jù),則執(zhí)行數(shù)據(jù)庫查詢,獲取結(jié)果后,會自動將該結(jié)果存入當(dāng)前 SqlSession 的一級緩存中,為后續(xù)相同條件的查詢提供數(shù)據(jù)支持。
為保障緩存數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)的一致性,一級緩存會被自動維護(hù):當(dāng)在當(dāng)前 SqlSession 中執(zhí)行 INSERT、UPDATE、DELETE 等寫操作時,MyBatis 會觸發(fā)一級緩存的清空機制,避免因數(shù)據(jù)更新導(dǎo)致緩存中留存舊數(shù)據(jù);當(dāng) SqlSession 執(zhí)行關(guān)閉、提交或回滾操作時,其對應(yīng)的一級緩存也會隨之失效并釋放資源。
這種機制使得一級緩存僅在單個數(shù)據(jù)庫會話內(nèi)有效,不同 SqlSession 之間的緩存相互隔離、無法共享,從而在減少同一會話內(nèi)重復(fù)查詢的數(shù)據(jù)庫訪問次數(shù)的同時,避免了跨會話的數(shù)據(jù)一致性風(fēng)險。
SqlMapConfig_cache.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>
<!-- 配置環(huán)境 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 加載映射的配置文件 -->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>需要注意的是,為比較輸出對象的是否為同一對象,我們比較輸出對象的引用地址,即 User 類不重寫 toString() 方法
測試方法
import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserTest_cache {
/**
* 證明一級緩存的存在
*/
@Test
public void run1() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig_cache.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//通過主鍵查詢
User user = mapper.findById(1);
System.out.println(user);
System.out.println("==================================");
//手動清空緩存
//sqlSession.clearCache();
//再查詢一次
User user1=mapper.findById(1);
System.out.println(user1);
sqlSession.close();
inputStream.close();
}
}盡管進(jìn)行了兩次查詢,但日志中僅出現(xiàn)了一條 SQL 語句的執(zhí)行記錄,且兩次查詢輸出的User對象引用地址完全相同,這說明第二次查詢并未重新執(zhí)行 SQL 去數(shù)據(jù)庫獲取數(shù)據(jù),而是直接復(fù)用了第一次查詢后緩存到內(nèi)存中的User對象,符合一級緩存緩存主線程同一會話中相同查詢條件的結(jié)果的特性。

執(zhí)行 sqlSession.clearCache();,手動清空緩存,這樣日志出現(xiàn)了兩條SQL語句,且兩次查詢輸出的User對象引用地址不同

import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserTest_cache {
@Test
public void run2() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig_cache.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findById(1);
System.out.println(user);
System.out.println("==================================");
SqlSession sqlSession1 = factory.openSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user1=mapper1.findById(1);
System.out.println(user1);
sqlSession.close();
inputStream.close();
}
}
兩次查詢分別在兩個獨立的SqlSession實例中執(zhí)行,而 MyBatis 的一級緩存作用域嚴(yán)格限定于單個SqlSession,這兩個會話各自維護(hù)一個獨立且初始為空的緩存。因此,第一次查詢命中第一個SqlSession的空緩存,觸發(fā)數(shù)據(jù)庫訪問并生成一條 SQL 日志,結(jié)果存入該會話的緩存;第二次查詢同樣命中第二個SqlSession的空緩存,再次觸發(fā)數(shù)據(jù)庫訪問并生成第二條 SQL 日志,結(jié)果存入第二個會話的緩存。由于兩次查詢返回的是兩個不同的User對象實例,因此它們的哈希碼標(biāo)識不同。這一現(xiàn)象清晰地證明了一級緩存的會話隔離性,即緩存數(shù)據(jù)無法在不同SqlSession之間共享。
二級緩存
MyBatis 的二級緩存是 SqlSessionFactory 級別的緩存,它在查詢時優(yōu)先被檢查,如果命中則直接返回數(shù)據(jù);若未命中,則繼續(xù)檢查當(dāng)前 SqlSession 的一級緩存,仍未命中才查詢數(shù)據(jù)庫,并將結(jié)果先寫入一級緩存,待 SqlSession 關(guān)閉或提交時,再將一級緩存中的數(shù)據(jù)同步到二級緩存中,供其他 SqlSession 共享。同時,為保證數(shù)據(jù)一致性,當(dāng)同一 Namespace 內(nèi)執(zhí)行任何增、刪、改操作時,該 Namespace 下的整個二級緩存會被自動清空,從而避免讀取到臟數(shù)據(jù)。
SqlMapConfig_cache.xml 中添加如下配置開啟全局緩存開關(guān)
<settings>
<!--開啟二級緩存-->
<setting name="cacheEnabled" value="true"/>
</settings>UserMapper.xml 中開啟二級緩存,表示該Mapper的Namespace將啟用二級緩存
<!--開啟二級緩存使用-->
<cache/>package com.qcby;
import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserTest_cache {
@Test
public void run3() throws IOException {
//加載配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig_cache.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findById(1);
System.out.println(user);
System.out.println("=====================");
//手動清空一級緩存
sqlSession.clearCache();
sqlSession.commit();
//關(guān)閉session
sqlSession.close();
SqlSession sqlSession1=factory.openSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user1=mapper1.findById(1);
System.out.println(user1);
sqlSession1.close();
inputStream.close();
}
}
第一個SqlSession執(zhí)行查詢時,因二級緩存和自身一級緩存均為空,故訪問數(shù)據(jù)庫并生成SQL日志,查詢結(jié)果存入一級緩存;在其commit并close后,MyBatis將結(jié)果序列化并寫入UserMapper對應(yīng)的二級緩存。第二個SqlSession執(zhí)行相同查詢時,直接命中二級緩存,因此沒有SQL日志輸出,且控制臺打印出“Cache Hit Ratio”表明緩存命中率,證明了跨SqlSession的數(shù)據(jù)共享;由于從二級緩存中獲取數(shù)據(jù)時,進(jìn)行了反序列化操作,生成的是一個全新的對象,而不是第一個SqlSession中的那個對象實例,所以兩次打印的User對象哈希碼不同。
UserMapper.xml 配置文件中設(shè)置如下內(nèi)容
<select id="findById" resultType="com.qcby.domain.User" parameterType="int" useCache="false">
select * from user where id = #{id};
</select>useCache 屬性用于控制當(dāng)前查詢是否使用二級緩存,當(dāng)Mapper.xml文件通過<cache>標(biāo)簽開啟了二級緩存后,該文件中所有的<select>語句默認(rèn)繼承此設(shè)置,即 useCache=“true”。設(shè)置 useCache=“false” 即禁用當(dāng)前這條查詢語句的二級緩存功能,MyBatis 在執(zhí)行查詢時,會完全跳過二級緩存的檢查,直接去查詢一級緩存。

需要注意的是如果沒有讓 User 類實現(xiàn) Serializable 序列化接口,會拋出 NotSerializableException 異常

到此這篇關(guān)于MyBatis框架—延遲加載與多級緩存的文章就介紹到這了,更多相關(guān)MyBatis延遲加載與多級緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Maven項目報錯:failed?to?execute?goal?org.apache.maven.plug
這篇文章主要介紹了解決Maven項目報錯:failed?to?execute?goal?org.apache.maven.plugins:maven-compiler-plugin:3.13.0的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-05-05
Java Swing中JDialog實現(xiàn)用戶登陸UI示例
這篇文章主要介紹了Java Swing中JDialog實現(xiàn)用戶登陸UI功能,結(jié)合完整實例形式分析了Swing使用JDialog實現(xiàn)用戶登陸UI界面窗口功能的步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
使用JMX監(jiān)控Zookeeper狀態(tài)Java API
今天小編就為大家分享一篇關(guān)于使用JMX監(jiān)控Zookeeper狀態(tài)Java API,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
Spring中的FactoryBean與BeanFactory詳細(xì)解析
這篇文章主要介紹了Spring中的FactoryBean與BeanFactory詳細(xì)解析,在Spring框架中,FactoryBean和BeanFactory是兩個關(guān)鍵的接口,用于創(chuàng)建和管理對象實例,它們在Spring的IoC(Inversion of Control,控制反轉(zhuǎn))容器中發(fā)揮著重要的作用,需要的朋友可以參考下2023-11-11

