最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis一二級(jí)緩存機(jī)制全解析

 更新時(shí)間:2025年12月19日 09:30:49   作者:佛祖讓我來(lái)巡山  
理解MyBatis的一二級(jí)緩存不僅有助于優(yōu)化應(yīng)用性能,還能避免因緩存不當(dāng)導(dǎo)致的數(shù)據(jù)一致性問(wèn)題,本文將從基礎(chǔ)概念到高級(jí)原理,全方位解析MyBatis緩存機(jī)制,感興趣的朋友跟隨小編一起看看吧

引言

在現(xiàn)代Web應(yīng)用中,數(shù)據(jù)庫(kù)訪問(wèn)往往是性能瓶頸之一。MyBatis作為流行的持久層框架,其緩存機(jī)制是提升應(yīng)用性能的關(guān)鍵特性。理解MyBatis的一二級(jí)緩存不僅有助于優(yōu)化應(yīng)用性能,還能避免因緩存不當(dāng)導(dǎo)致的數(shù)據(jù)一致性問(wèn)題。本文將從基礎(chǔ)概念到高級(jí)原理,全方位解析MyBatis緩存機(jī)制。

一、緩存的基本概念:為什么需要緩存?

1.1 緩存的價(jià)值

想象一下,如果你每次需要知道時(shí)間都去天文臺(tái)查詢,效率會(huì)很低。相反,看一眼手表(緩存)就能立即獲取時(shí)間。MyBatis緩存扮演的就是這個(gè)“手表”的角色,它避免了頻繁訪問(wèn)數(shù)據(jù)庫(kù)(天文臺(tái)),極大提升了查詢效率。

1.2 緩存的經(jīng)濟(jì)學(xué)原理

  • 時(shí)間局部性:剛被訪問(wèn)的數(shù)據(jù)很可能再次被訪問(wèn)
  • 空間局部性:相鄰的數(shù)據(jù)很可能被一起訪問(wèn)
  • 訪問(wèn)成本:內(nèi)存訪問(wèn)(納秒級(jí))vs 磁盤/網(wǎng)絡(luò)訪問(wèn)(毫秒級(jí))

二、一級(jí)緩存:SqlSession級(jí)別的緩存

2.1 什么是SqlSession?

在深入一級(jí)緩存前,需要先理解SqlSession。SqlSession不是數(shù)據(jù)庫(kù)連接(Connection),而是一次數(shù)據(jù)庫(kù)對(duì)話的抽象:

// SqlSession相當(dāng)于一次完整對(duì)話,不是一通電話
SqlSession session = sqlSessionFactory.openSession();
try {
    // 對(duì)話中的多次查詢
    userMapper.getUser(1);  // 第一次查詢
    orderMapper.getOrders(1);  // 第二次查詢
    accountMapper.getBalance(1);  // 第三次查詢
    session.commit();  // 確認(rèn)對(duì)話內(nèi)容
} finally {
    session.close();  // 結(jié)束對(duì)話
}

2.2 一級(jí)緩存的核心特性

作用范圍:SqlSession內(nèi)部(一次對(duì)話)
默認(rèn)狀態(tài):自動(dòng)開啟,無(wú)法關(guān)閉
生命周期:隨SqlSession創(chuàng)建而創(chuàng)建,隨其關(guān)閉而銷毀

2.3 一級(jí)緩存的工作原理

// 示例代碼展示一級(jí)緩存行為
public void demonstrateLevel1Cache() {
    SqlSession session = sqlSessionFactory.openSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    System.out.println("第一次查詢用戶1:");
    User user1 = mapper.selectById(1);  // 發(fā)SQL:SELECT * FROM user WHERE id=1
    System.out.println("第二次查詢用戶1:");
    User user2 = mapper.selectById(1);  // 不發(fā)SQL!從一級(jí)緩存讀取
    System.out.println("查詢用戶2:");
    User user3 = mapper.selectById(2);  // 發(fā)SQL:參數(shù)不同,緩存未命中
    System.out.println("修改用戶1:");
    mapper.updateUser(user1);  // 清空一級(jí)緩存
    System.out.println("再次查詢用戶1:");
    User user4 = mapper.selectById(1);  // 發(fā)SQL:緩存被清空
    session.close();
}

2.4 一級(jí)緩存的數(shù)據(jù)結(jié)構(gòu)

一級(jí)緩存的實(shí)現(xiàn)非常簡(jiǎn)單直接:

// 一級(jí)緩存的核心實(shí)現(xiàn)類
public class PerpetualCache implements Cache {
    // 核心:就是一個(gè)ConcurrentHashMap!
    private final Map<Object, Object> cache = new ConcurrentHashMap<>();
    @Override
    public void putObject(Object key, Object value) {
        cache.put(key, value);  // 簡(jiǎn)單的Map.put()
    }
    @Override
    public Object getObject(Object key) {
        return cache.get(key);  // 簡(jiǎn)單的Map.get()
    }
}

緩存Key的生成規(guī)則

// CacheKey包含以下要素,決定兩個(gè)查詢是否"相同"
// 1. Mapper Id(namespace + method)
// 2. 分頁(yè)參數(shù)(offset, limit)
// 3. SQL語(yǔ)句
// 4. 參數(shù)值
// 5. 環(huán)境Id
// 這意味著:即使SQL相同,參數(shù)不同,也會(huì)生成不同的CacheKey

2.5 一級(jí)緩存的失效場(chǎng)景

  1. 執(zhí)行任何UPDATE/INSERT/DELETE操作
  2. 手動(dòng)調(diào)用clearCache()
  3. 設(shè)置flushCache="true"
  4. SqlSession關(guān)閉
  5. 查詢參數(shù)變化(因?yàn)镃acheKey不同)

三、二級(jí)緩存:Mapper級(jí)別的全局緩存

3.1 二級(jí)緩存的核心特性

作用范圍:Mapper級(jí)別(跨SqlSession共享)
默認(rèn)狀態(tài):默認(rèn)關(guān)閉,需要手動(dòng)開啟
生命周期:隨應(yīng)用運(yùn)行而存在

3.2 二級(jí)緩存的配置

<!-- 1. 全局配置開啟二級(jí)緩存 -->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
<!-- 2. Mapper XML中配置 -->
<mapper namespace="com.example.UserMapper">
    <!-- 基本配置 -->
    <cache/>
    <!-- 詳細(xì)配置 -->
    <cache
        eviction="LRU"           <!-- 淘汰策略 -->
        flushInterval="60000"    <!-- 刷新間隔(毫秒) -->
        size="1024"              <!-- 緩存對(duì)象數(shù) -->
        readOnly="true"          <!-- 是否只讀 -->
        blocking="false"/>       <!-- 是否阻塞 -->
</mapper>
<!-- 3. 在具體查詢上使用緩存 -->
<select id="selectById" resultType="User" useCache="true">
    SELECT * FROM user WHERE id = #{id}
</select>
<!-- 4. 增刪改操作刷新緩存 -->
<update id="updateUser" flushCache="true">
    UPDATE user SET name = #{name} WHERE id = #{id}
</update>

3.3 二級(jí)緩存的數(shù)據(jù)結(jié)構(gòu)

二級(jí)緩存不像一級(jí)緩存那么簡(jiǎn)單,它采用了裝飾器模式

二級(jí)緩存裝飾器鏈(層層包裝):
┌─────────────────────────┐
│  SerializedCache        │ ← 序列化存儲(chǔ)
│  LoggingCache           │ ← 日志統(tǒng)計(jì)
│  SynchronizedCache      │ ← 線程安全
│  LruCache               │ ← LRU淘汰
│  PerpetualCache         │ ← 基礎(chǔ)HashMap
└─────────────────────────┘

每個(gè)裝飾器都有特定功能:

  • PerpetualCache:基礎(chǔ)存儲(chǔ),使用HashMap
  • LruCache:最近最少使用淘汰
  • SynchronizedCache:保證線程安全
  • LoggingCache:記錄命中率
  • SerializedCache:序列化對(duì)象,防止修改

3.4 二級(jí)緩存的工作流程

public void demonstrateLevel2Cache() {
    // 用戶A查詢(第一個(gè)訪問(wèn)者)
    SqlSession sessionA = sqlSessionFactory.openSession();
    UserMapper mapperA = sessionA.getMapper(UserMapper.class);
    User user1 = mapperA.selectById(1);  // 查詢數(shù)據(jù)庫(kù)
    sessionA.close();  // 關(guān)鍵:關(guān)閉時(shí)才會(huì)寫入二級(jí)緩存
    // 用戶B查詢(不同SqlSession)
    SqlSession sessionB = sqlSessionFactory.openSession();
    UserMapper mapperB = sessionB.getMapper(UserMapper.class);
    User user2 = mapperB.selectById(1);  // 從二級(jí)緩存讀取,不發(fā)SQL
    // 管理員更新數(shù)據(jù)
    SqlSession sessionC = sqlSessionFactory.openSession();
    UserMapper mapperC = sessionC.getMapper(UserMapper.class);
    mapperC.updateUser(user1);  // 清空相關(guān)二級(jí)緩存
    sessionC.commit();
    sessionC.close();
    // 用戶D再次查詢
    SqlSession sessionD = sqlSessionFactory.openSession();
    UserMapper mapperD = sessionD.getMapper(UserMapper.class);
    User user3 = mapperD.selectById(1);  // 緩存被清,重新查詢數(shù)據(jù)庫(kù)
    sessionD.close();
}

3.5 二級(jí)緩存的同步機(jī)制

二級(jí)緩存有一個(gè)重要特性:事務(wù)提交后才更新。這意味著:

// 場(chǎng)景:事務(wù)內(nèi)查詢,事務(wù)提交前其他會(huì)話看不到更新
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper mapper1 = session1.getMapper(UserMapper.class);
// 修改數(shù)據(jù),但未提交
mapper1.updateUser(user);
// 此時(shí)二級(jí)緩存還未更新
// 另一個(gè)會(huì)話查詢
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user2 = mapper2.selectById(1);  // 可能讀到舊數(shù)據(jù)!
session1.commit();  // 提交后,二級(jí)緩存才會(huì)更新
// 之后的新查詢才會(huì)看到新數(shù)據(jù)

四、一二級(jí)緩存的對(duì)比與選擇

4.1 核心差異對(duì)比

特性一級(jí)緩存二級(jí)緩存
作用范圍SqlSession內(nèi)部Mapper級(jí)別,跨SqlSession
默認(rèn)狀態(tài)開啟關(guān)閉
數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單HashMap裝飾器鏈
共享性私有,不共享公共,所有會(huì)話共享
生命周期隨SqlSession創(chuàng)建銷毀隨應(yīng)用運(yùn)行持久存在
性能影響極?。▋?nèi)存訪問(wèn))中等(可能有序列化開銷)
適用場(chǎng)景會(huì)話內(nèi)重復(fù)查詢跨會(huì)話共享查詢

4.2 生活化比喻

一級(jí)緩存 = 私人對(duì)話記憶

  • 你和朋友的聊天內(nèi)容,只有你們兩人知道
  • 聊天結(jié)束(SqlSession關(guān)閉),記憶逐漸模糊

二級(jí)緩存 = 公司公告欄

  • 重要通知寫在公告欄,所有員工都能看到
  • 通知更新時(shí),需要擦掉舊的,寫上新的
  • 公告欄內(nèi)容持久存在,直到被更新

4.3 使用場(chǎng)景建議

適合一級(jí)緩存的場(chǎng)景:

// 場(chǎng)景1:方法內(nèi)多次查詢相同數(shù)據(jù)
public void processOrder(Long orderId) {
    Order order1 = validateOrder(orderId);      // 第一次查數(shù)據(jù)庫(kù)
    Order order2 = calculateDiscount(orderId);  // 走一級(jí)緩存
    Order order3 = generateInvoice(orderId);    // 走一級(jí)緩存
}
// 場(chǎng)景2:循環(huán)內(nèi)查詢
for (int i = 0; i < 100; i++) {
    Config config = configMapper.getConfig("system_timeout");
    // 只有第一次查數(shù)據(jù)庫(kù),后續(xù)99次走緩存
}

適合二級(jí)緩存的場(chǎng)景:

// 場(chǎng)景1:讀多寫少的配置數(shù)據(jù)
SystemConfig config = configMapper.getConfig("app_settings");
// 多個(gè)用戶頻繁讀取,很少修改
// 場(chǎng)景2:熱門商品信息
Product product = productMapper.getHotProduct(666);
// 商品詳情頁(yè),大量用戶訪問(wèn)同一商品
// 場(chǎng)景3:靜態(tài)字典數(shù)據(jù)
List<City> cities = addressMapper.getAllCities();
// 城市列表,很少變化

不適合緩存的場(chǎng)景:

// 場(chǎng)景1:實(shí)時(shí)性要求高的數(shù)據(jù)
Stock stock = stockMapper.getRealTimeStock(productId);
// 庫(kù)存信息,需要實(shí)時(shí)準(zhǔn)確
// 場(chǎng)景2:頻繁更新的數(shù)據(jù)
UserBalance balance = accountMapper.getBalance(userId);
// 用戶余額,每次交易都變化
// 場(chǎng)景3:大數(shù)據(jù)量查詢
List<Log> logs = logMapper.getTodayLogs();
// 數(shù)據(jù)量大,緩存占用內(nèi)存過(guò)多

五、緩存的高級(jí)特性與原理

5.1 緩存淘汰策略

MyBatis提供了多種淘汰策略:

<cache eviction="策略類型" size="緩存大小">

可用策略:

  • LRU(Least Recently Used):最近最少使用(默認(rèn))
  • FIFO(First In First Out):先進(jìn)先出
  • SOFT:軟引用,內(nèi)存不足時(shí)被GC回收
  • WEAK:弱引用,GC時(shí)立即回收

5.2 LRU緩存的實(shí)現(xiàn)原理

public class LruCache implements Cache {
    private final Cache delegate;
    // 使用LinkedHashMap實(shí)現(xiàn)LRU
    private Map<Object, Object> keyMap;
    private Object eldestKey;
    public void setSize(final int size) {
        keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
                boolean tooBig = size() > size;
                if (tooBig) {
                    eldestKey = eldest.getKey();
                }
                return tooBig;
            }
        };
    }
    @Override
    public Object getObject(Object key) {
        // 訪問(wèn)時(shí)更新順序
        keyMap.get(key);
        return delegate.getObject(key);
    }
}

5.3 緩存查詢的完整流程

查詢執(zhí)行流程:
1. 請(qǐng)求到達(dá)CachingExecutor(二級(jí)緩存入口)
2. 生成CacheKey(包含SQL、參數(shù)等信息)
3. 查詢二級(jí)緩存
   └─ 命中 → 返回結(jié)果
   └─ 未命中 → 繼續(xù)
4. 查詢一級(jí)緩存
   └─ 命中 → 返回結(jié)果,并放入二級(jí)緩存(事務(wù)提交時(shí))
   └─ 未命中 → 繼續(xù)
5. 查詢數(shù)據(jù)庫(kù)
6. 結(jié)果存入一級(jí)緩存
7. 事務(wù)提交時(shí),一級(jí)緩存刷入二級(jí)緩存
8. 返回結(jié)果

六、緩存的最佳實(shí)踐與避坑指南

6.1 最佳實(shí)踐

1. 合理配置緩存大小

<!-- 根據(jù)數(shù)據(jù)特點(diǎn)設(shè)置合適的大小 -->
<cache size="1024"/>  <!-- 緩存1024個(gè)對(duì)象 -->

2. 設(shè)置合理的刷新間隔

<!-- 對(duì)于變化不頻繁但需要定期更新的數(shù)據(jù) -->
<cache flushInterval="1800000"/>  <!-- 30分鐘自動(dòng)刷新 -->

3. 選擇性使用緩存

<!-- 某些查詢跳過(guò)緩存 -->
<select id="getRealTimeData" useCache="false">
    SELECT * FROM realtime_table
</select>
<!-- 某些查詢強(qiáng)制刷新緩存 -->
<select id="getImportantData" flushCache="true">
    SELECT * FROM important_table
</select>

4. 關(guān)聯(lián)查詢的緩存策略

<!-- 關(guān)聯(lián)查詢時(shí),使用cache-ref同步緩存 -->
<mapper namespace="com.example.UserMapper">
    <cache/>
    <!-- 其他配置 -->
</mapper>
<mapper namespace="com.example.OrderMapper">
    <!-- 引用UserMapper的緩存 -->
    <cache-ref namespace="com.example.UserMapper"/>
</mapper>

6.2 常見問(wèn)題與解決方案

問(wèn)題1:臟讀問(wèn)題

場(chǎng)景:一個(gè)會(huì)話修改數(shù)據(jù)但未提交,另一個(gè)會(huì)話從二級(jí)緩存讀取到舊數(shù)據(jù)。

解決方案

// 設(shè)置事務(wù)隔離級(jí)別
@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateUser(User user) {
    userMapper.updateUser(user);
}
// 或者在Mapper中設(shè)置flushCache
@Update("UPDATE user SET name=#{name} WHERE id=#{id}")
@Options(flushCache = Options.FlushCachePolicy.TRUE)
int updateUser(User user);

問(wèn)題2:內(nèi)存溢出

場(chǎng)景:緩存大量數(shù)據(jù)導(dǎo)致JVM內(nèi)存不足。

解決方案

  1. 設(shè)置合理的緩存大小和淘汰策略
  2. 使用軟引用/弱引用緩存
  3. 定期清理不活躍的緩存

問(wèn)題3:分布式環(huán)境緩存不一致

場(chǎng)景:多臺(tái)服務(wù)器,每臺(tái)有自己的緩存,數(shù)據(jù)不一致。

解決方案

  1. 使用集中式緩存(Redis、Memcached)替代默認(rèn)二級(jí)緩存
  2. 實(shí)現(xiàn)自定義Cache接口:
public class RedisCache implements Cache {
    private JedisPool jedisPool;
    @Override
    public void putObject(Object key, Object value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.set(serialize(key), serialize(value));
        }
    }
    @Override
    public Object getObject(Object key) {
        try (Jedis jedis = jedisPool.getResource()) {
            byte[] value = jedis.get(serialize(key));
            return deserialize(value);
        }
    }
}

問(wèn)題4:緩存穿透

場(chǎng)景:查詢不存在的數(shù)據(jù),每次都查數(shù)據(jù)庫(kù)。

解決方案

// 緩存空對(duì)象
public User getUser(Long id) {
    User user = userMapper.selectById(id);
    if (user == null) {
        // 緩存空值,設(shè)置短過(guò)期時(shí)間
        cacheNullValue(id);
        return null;
    }
    return user;
}

6.3 監(jiān)控與調(diào)試

開啟緩存日志

# 查看緩存命中情況
logging.level.org.mybatis=DEBUG
logging.level.com.example.mapper=TRACE

監(jiān)控緩存命中率

// 獲取緩存統(tǒng)計(jì)信息
Cache cache = sqlSession.getConfiguration()
    .getCache("com.example.UserMapper");
if (cache instanceof LoggingCache) {
    LoggingCache loggingCache = (LoggingCache) cache;
    System.out.println("命中次數(shù): " + loggingCache.getHitCount());
    System.out.println("未命中次數(shù): " + loggingCache.getMissCount());
    System.out.println("命中率: " + 
        (loggingCache.getHitCount() * 100.0 / 
         (loggingCache.getHitCount() + loggingCache.getMissCount())) + "%");
}

七、總結(jié)與思考

7.1 核心要點(diǎn)回顧

  1. 一級(jí)緩存:SqlSession級(jí)別,自動(dòng)開啟,基于HashMap,簡(jiǎn)單高效
  2. 二級(jí)緩存:Mapper級(jí)別,需手動(dòng)開啟,基于裝飾器模式,功能豐富
  3. 緩存Key:由SQL、參數(shù)等要素生成,決定查詢是否"相同"
  4. 事務(wù)同步:二級(jí)緩存在事務(wù)提交后才更新,避免臟讀
  5. 適用場(chǎng)景:根據(jù)數(shù)據(jù)特點(diǎn)選擇合適的緩存策略

7.2 設(shè)計(jì)思想啟示

MyBatis緩存設(shè)計(jì)體現(xiàn)了幾個(gè)重要軟件設(shè)計(jì)原則:

  1. 單一職責(zé)原則:每個(gè)緩存裝飾器只負(fù)責(zé)一個(gè)功能
  2. 開閉原則:通過(guò)裝飾器模式,無(wú)需修改原有代碼即可擴(kuò)展功能
  3. 接口隔離:Cache接口定義清晰,便于自定義實(shí)現(xiàn)

7.3 實(shí)際應(yīng)用建議

在實(shí)際項(xiàng)目中:

  1. 從小開始:先使用一級(jí)緩存,確有需要再開啟二級(jí)緩存
  2. 測(cè)試驗(yàn)證:上線前充分測(cè)試緩存效果和內(nèi)存占用
  3. 監(jiān)控調(diào)整:生產(chǎn)環(huán)境監(jiān)控緩存命中率,根據(jù)實(shí)際情況調(diào)整配置
  4. 文檔記錄:記錄緩存配置和策略,便于團(tuán)隊(duì)協(xié)作和維護(hù)

7.4 未來(lái)展望

隨著微服務(wù)和云原生架構(gòu)的普及,MyBatis緩存也在演進(jìn):

  1. 分布式緩存集成:更好支持Redis等分布式緩存
  2. 多級(jí)緩存策略:本地緩存+分布式緩存的組合使用
  3. 智能緩存管理:基于訪問(wèn)模式的自動(dòng)緩存優(yōu)化

結(jié)語(yǔ)

MyBatis緩存機(jī)制是一個(gè)看似簡(jiǎn)單實(shí)則精妙的設(shè)計(jì)。理解它不僅能幫助我們優(yōu)化應(yīng)用性能,還能加深對(duì)緩存設(shè)計(jì)模式的理解。記住,緩存是提升性能的利器,但也可能成為數(shù)據(jù)一致的陷阱。合理使用、謹(jǐn)慎配置、持續(xù)監(jiān)控,才能讓緩存真正為應(yīng)用賦能。

緩存不是銀彈,而是需要精心調(diào)校的利器。 在實(shí)際開發(fā)中,應(yīng)根據(jù)業(yè)務(wù)特點(diǎn)、數(shù)據(jù)特性和訪問(wèn)模式,選擇最合適的緩存策略,在性能與一致性之間找到最佳平衡點(diǎn)。

到此這篇關(guān)于MyBatis一二級(jí)緩存機(jī)制全解析的文章就介紹到這了,更多相關(guān)MyBatis一二級(jí)緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring boot 異步線程池的使用詳解

    spring boot 異步線程池的使用詳解

    本文介紹了如何在SpringBoot項(xiàng)目中配置異步線程池,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2026-04-04
  • Java中MyBatis Plus知識(shí)點(diǎn)總結(jié)

    Java中MyBatis Plus知識(shí)點(diǎn)總結(jié)

    在本篇文章里小編給大家整理一篇關(guān)于Java中MyBatis Plus知識(shí)點(diǎn)總結(jié),需要的朋友們參考下。
    2019-10-10
  • Mybatis-Plus多種批量插入方案對(duì)比小結(jié)

    Mybatis-Plus多種批量插入方案對(duì)比小結(jié)

    在項(xiàng)目中優(yōu)化Mybatis-Plus批量插入性能是關(guān)鍵,通過(guò)比較不同方案,本文就來(lái)介紹一下Mybatis-Plus多種批量插入方案對(duì)比小結(jié),感興趣都的可以了解一下
    2024-10-10
  • SpringBoot實(shí)現(xiàn)配置文件的替換

    SpringBoot實(shí)現(xiàn)配置文件的替換

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)配置文件的替換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java實(shí)現(xiàn)鮮花銷售系統(tǒng)

    java實(shí)現(xiàn)鮮花銷售系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)鮮花銷售系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Mybatis詳解動(dòng)態(tài)SQL以及單表多表查詢的應(yīng)用

    Mybatis詳解動(dòng)態(tài)SQL以及單表多表查詢的應(yīng)用

    MyBatis的動(dòng)態(tài)SQL是基于OGNL表達(dá)式的,它可以幫助我們方便的在SQL語(yǔ)句中實(shí)現(xiàn)某些邏輯,下面這篇文章主要給大家介紹了關(guān)于Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語(yǔ)句的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 一文搞懂Spring中Bean的生命周期

    一文搞懂Spring中Bean的生命周期

    這篇文章主要為大家介紹了Spring中Bean生命周期的使用及控制,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的可以學(xué)習(xí)一下
    2022-06-06
  • Java ForkJoin 框架全面解析:分而治之的并行編程藝術(shù)

    Java ForkJoin 框架全面解析:分而治之的并行編程藝術(shù)

    本文介紹了Java Fork/JoinJoin框架用于并行執(zhí)行任務(wù)的思想、核心組件和使用方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2026-05-05
  • 輕松掌握java責(zé)任鏈模式

    輕松掌握java責(zé)任鏈模式

    這篇文章主要幫助大家輕松掌握java責(zé)任鏈模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • 一文帶你掌握J(rèn)ava中Scanner類的使用

    一文帶你掌握J(rèn)ava中Scanner類的使用

    Scanner類是java.util包中的一個(gè)類,常用于控制臺(tái)的輸入,當(dāng)需要使用控制臺(tái)輸入時(shí)即可調(diào)用這個(gè)類。本文將通過(guò)一些簡(jiǎn)單的例子為大家介紹一下Java中Scanner類的使用,需要的可以參考一下
    2023-04-04

最新評(píng)論

阿鲁科尔沁旗| 襄垣县| 繁昌县| 五台县| 桃园县| 临颍县| 疏附县| 万全县| 伊宁县| 牡丹江市| 福泉市| 磐石市| 福鼎市| 凤冈县| 革吉县| 方山县| 香河县| 蓬莱市| 蒙阴县| 和顺县| 梁河县| 南安市| 建德市| 玉屏| 宜兰县| 大新县| 广宗县| 涪陵区| 利辛县| 武鸣县| 西青区| 治县。| 佳木斯市| 金堂县| 永修县| 钟祥市| 永济市| 马鞍山市| 和静县| 衡阳市| 沾益县|