主頁 > 後端開發 > Hibernate 基本操作、懶加載以及快取

Hibernate 基本操作、懶加載以及快取

2023-05-11 07:32:24 後端開發

前言

上一篇咱們介紹了 Hibernate 以及寫了一個 Hibernate 的工具類,快速入門體驗了一波 Hibernate 的使用,我們只需通過 Session 物件就能實作資料庫的操作了,

現在,這篇介紹使用 Hibernate 進行基本的 CRUD、懶加載以及快取的知識,

提示:如果你還沒看上一篇,那么建議你看完上一篇再來看這篇,

上一篇:一文快速入門體驗 Hibernate

基本的 CRUD

以下代碼均寫在測驗類 HibernateTest 中

插入操作

這個在上一篇已經演示過,這里便不再演示,

查詢操作

查詢有 2 種方式,通過 Session 物件的 get 方法 或者 load 方法來實作查詢,主要將查詢的資料結果封裝到一個 Java 物件中,

  1. get 方法
    @Test
    public void queryByGet() {
        // 獲取 Session 物件
        Session session = HibernateUtil.getSession();
        try {
            // 使用 get() 方法,第一個引數是持久化類的型別引數,第二個引數是主鍵標識引數,如果沒有匹配的記錄,那么會回傳 null
            User user = session.get(User.class, new Integer("1"));
            System.out.println("用戶ID:" + user.getId());
        } catch (Exception e) {
            System.out.println("查詢User資料失敗!");
            e.printStackTrace();
        } finally{
            // 關閉 Session 物件
            HibernateUtil.closeSession();
        }
    }

控制臺輸出:可以看到,執行了查詢 SQL,并列印了用戶 ID,

INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
五月 08, 2023 11:38:59 下午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.password as password3_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
用戶ID:1

  1. load 方法
    @Test
    public void queryByLoad() {
        // 獲取 Session 物件
        Session session = HibernateUtil.getSession();
        try {
            // 使用 load() 方法,它回傳物件的代理,只有該代理被呼叫時,Hibernate 才會真正去執行 SQL 查詢
            User user = session.load(User.class, new Integer("1"));
            // ID 是已知的,不用進行查詢
            System.out.println("用戶ID:" + user.getId());
            // 此時該代理被呼叫,就執行 SQL 陳述句,得到真正的資料記錄
            System.out.println("用戶名稱:" + user.getName());
        } catch (Exception e) {
            System.out.println("查詢User資料失敗!");
            e.printStackTrace();
        } finally{
            // 關閉 Session 物件
            HibernateUtil.closeSession();
        }
    }

控制臺輸出:

五月 08, 2023 11:40:13 下午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
五月 08, 2023 11:40:14 下午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
用戶ID:1
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.password as password3_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
用戶名稱:god23bin

可以看到,是先列印用戶ID的,這里還沒有執行查詢 SQL,直到下一條陳述句中的 user.getName() 的執行,查詢的 SQL 陳述句才被 Hibernate 執行

修改操作

想對某條資料進行修改操作,那么需要將它先查詢出來,然后進行修改,這里就執行了兩條 SQL,保險起見,開啟事務,然后執行這兩條 SQL,接著提交事務,當然,這兩條 SQL,Hibernate 幫我們寫的啦!

    @Test
    public void update() {
        // 獲取 Session 物件
        Session session = HibernateUtil.getSession();
        try {
            // 開啟事務
            session.beginTransaction();
            // 進行查詢,將結果封裝成 user 物件
            User user = session.get(User.class, new Integer("1"));
            // 對 user 物件進行修改
            user.setName("公眾號:god23bin");
            user.setPassword("456789");
            // 提交事務
            session.getTransaction().commit();
        } catch (Exception e) {
            // 發生例外,則回滾事務
            session.getTransaction().rollback();
            System.out.println("修改User資料失敗!");
            e.printStackTrace();
        } finally{
            // 關閉 Session 物件
            HibernateUtil.closeSession();
        }
    }

控制臺輸出:

五月 09, 2023 12:00:16 上午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
五月 09, 2023 12:00:17 上午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.password as password3_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        name=?,
        password=? 
    where
        id=?
        

可以看到運行前和運行后,資料的變化,如圖:

image-20230509000227733

如果螢屏前的小伙伴是按照我的步驟一步一步跟下來,那么你可能會遇到中文亂碼的問題,此時需要在 hibernate.cfg.xml 組態檔中修改 URL,加上兩個引數 useUnicode=true&characterEncoding=UTF-8,如下:

<property name="connection.url">jdbc:mysql://localhost:3306/demo_hibernate?useUnicode=true&amp;characterEncoding=UTF-8</property>

洗掉操作

洗掉操作需要先把資料查詢出來,然后通過 Session 物件的 delete 方法將其洗掉,代碼如下:

    @Test
    public void delete() {
        // 獲取 Session 物件
        Session session = HibernateUtil.getSession();
        try {
            session.beginTransaction();
            User user = session.get(User.class, new Integer("1"));
            // 洗掉操作
            session.delete(user);
            session.getTransaction().commit();
        } catch (Exception e) {
            session.getTransaction().rollback();
            System.out.println("洗掉User資料失敗!");
            e.printStackTrace();
        } finally{
            // 關閉 Session 物件
            HibernateUtil.closeSession();
        }
    }

控制臺輸出:

五月 09, 2023 12:10:09 上午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
五月 09, 2023 12:10:10 上午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.password as password3_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    delete 
    from
        user 
    where
        id=?

關于 Hibernate 中物件的狀態

在Hibernate中,物件的狀態有 4 種,分別為 Transient、Persistent、Detached、Removed,譯名就比較多,方便起見,我選擇 3 個字的譯名:

  1. 瞬時態(Transient):當一個物件被實體化后,它處于瞬時態,簡單理解,就是 new 操作之后,瞬時態的物件沒有與之關聯的資料庫記錄,并且沒有被 Hibernate 的 Session 管理,當將瞬時態的物件關聯到持久態物件或通過 Session 物件的 savepersist 等方法進行持久化操作后,該物件的狀態會發生變化,轉成持久態,
  2. 持久態(Persistent):當一個物件與 Hibernate 的 Session 關聯后,它就處于持久態,持久態的物件有與之對應的資料庫記錄,并且被 Hibernate 的 Session 管理,對持久態物件的任何更改都會自動同步到資料庫,持久態物件可以通過Session的 getload 等方法從資料庫中獲取,或者通過 saveupdatepersist 等方法進行持久化操作,
  3. 游離態(Detached):當一個持久態物件與 Hibernate 的 Session 分離后,它處于游離態,游離態的物件仍然有與之對應的資料庫記錄,但不再受 Hibernate 的 Session 管理,對游離態物件的更改不會自動同步到資料庫,可以通過 Session 的 evictclear 等方法將持久態物件轉變為游離態物件,或者通過 Session 的 merge 方法將游離態物件重新關聯到 Session 中,
  4. 洗掉態(Removed):當一個持久態物件被從 Hibernate 的 Session中洗掉后,它處于洗掉態,洗掉態的物件仍然有與之對應的資料庫記錄,但即將被從資料庫中洗掉,洗掉態物件可以通過 Session 的delete 方法進行洗掉操作,

Hibernate 通過跟蹤物件的狀態變化,實作了物件與資料庫的同步,在 Hibernate 的事務管理中,物件的狀態轉換是自動進行的,我們無需手動操作,Hibernate 會根據物件的狀態進行相應的資料庫操作,保證物件與資料庫的一致性,

需要注意的是,Hibernate 的物件狀態與資料庫的操作并不是一一對應的,Hibernate 提供了一系列的持久化方法和操作,我們可以根據具體的需求選擇合適的方法來進行物件狀態的轉換和資料庫操作,對于復雜的業務邏輯和資料處理,需要仔細理解和管理物件的狀態,以避免資料不一致的問題,

懶加載

Hibernate 的懶加載(Lazy Loading)是一種延遲加載策略,它允許程式在需要訪問相關資料時才從資料庫中加載關聯物件的屬性或集合,

在 Hibernate 中,懶加載是通過使用代理物件來實作的,實際上,我們在演示 Session 物件的 load() 方法時,就是懶加載了,一開始回傳的是代理物件,并沒有直接查詢資料庫,而是直到該代理物件的屬性或方法被呼叫時,Hibernate 會根據需要自動執行額外的資料庫查詢,從而延遲加載關聯的資料,

這就是懶加載,等到需要的時候才去加載,

懶加載的主要優點是可以提高系統性能和減少不必要的資料庫查詢,如果一個物件關聯的屬性或集合在業務邏輯中很少被使用,懶加載可以避免不必要的資料庫訪問,減輕資料庫負載,

除了 load 方法實作的懶加載,我們還可以通過設定映射檔案中的 <property> 標簽的 lazy 屬性實作懶加載:

<property name="name" type="string" lazy="true" /> <!-- name 屬性被設定成懶加載-->

快取

快取是一種臨時存盤資料的方式,將資料保存在更快速的存盤介質(如記憶體)中,以便將來能夠快速訪問和檢索,

Hibernate 提供了快取的技術,主要用于存盤物體物件以及查詢的結果集,快取分為一級快取(Session 快取)和二級快取(Session Factory 快取)

一級快取

一級快取是與 Session 相關聯的快取,它存盤了從資料庫中讀取的物體物件,在同一個 Session 中,當多次查詢相同的資料時,Session 首先會根據對應的持久化類和唯一性標識(一般指的是ID)去快取中查找是否存在該資料,如果存在,則直接從快取中獲取,而不再訪問資料庫;如果不存在,則繼續向二級快取種查找,

一級快取是默認開啟的,可以提高讀取性能,

示例:

    @Test
    public void testFirstLevelCache() {
        Session session = HibernateUtil.getSession();
        try {
            System.out.println("第一次查詢:");
            User user = session.get(User.class, new Integer("2"));
            System.out.println("用戶名:" + user.getName());
            
            System.out.println("第二次查詢:");
            User user2 = session.get(User.class, new Integer("2"));
            System.out.println("用戶名:" + user2.getName());
        } catch (Exception e) {
            System.out.println("查詢User資料失敗!");
            e.printStackTrace();
        } finally{
            // 關閉 Session 物件
            HibernateUtil.closeSession();
        }
    }

控制臺輸出:

五月 09, 2023 9:35:31 下午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
五月 09, 2023 9:35:32 下午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
第一次查詢:
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.password as password3_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
用戶名:god23bin
第二次查詢:
用戶名:god23bin

可以看到,第二次查詢是沒有執行 SQL 的,直接從一級快取中獲取,

二級快取

二級快取是在 SessionFactory 級別上的快取,用于快取多個 Session 之間共享的資料,它可以減少對資料庫的訪問次數,提高性能和擴展性,二級快取可以存盤物體物件、集合物件以及查詢結果集,

由于 Hibernate 本身并未提供二級快取的具體實作,所以需要借助其他快取插件或者說策略來實作二級快取,比如 Ehcache、Redis 等,

我們這里直接使用 Ehcache,

  1. 引入依賴項
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>5.6.14.Final</version>
</dependency>

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.10.0</version>
</dependency>
  1. 開啟二級快取

二級快取默認是關閉的,我們需要手動開啟,在 hibernate.cfg.xml 中開啟二級快取:

<?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
		...
        <!-- 開啟二級快取 -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- 開啟查詢快取 -->
        <property name="hibernate.cache.use_query_cache">true</property>
        <!-- 指定使用的快取實作類 -->
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.internal.SingletonEhcacheRegionFactory</property>
    </session-factory>
</hibernate-configuration>
  1. 創建快取組態檔

我們在 /src/main/resources 目錄下創建快取組態檔 ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <!-- 硬碟存盤:將快取中暫時不使用的物件,持久化到硬碟 -->
    <!-- path 屬性:指定在硬碟上存盤物件的路徑 -->
    <!-- java.io.tmpdir 是默認的臨時檔案路徑, 可以通過右邊的方式列印出具體的檔案路徑: System.out.println(System.getProperty("java.io.tmpdir")); -->
    <diskStore path="java.io.tmpdir"/>


    <!-- defaultCache:默認的快取策略 -->
    <!-- eternal 屬性:設定快取的elements是否永遠不過期,如果為true,則快取的資料始終有效,如果為false那么還要根據timeToIdleSeconds,timeToLiveSeconds判斷 -->
    <!-- maxElementsInMemory 屬性:在記憶體中快取的element的最大數目 -->
    <!-- overflowToDisk 屬性:如果記憶體中資料超過記憶體限制,是否要快取到硬碟上 -->
    <!-- diskPersistent 屬性:是否在硬碟上持久化,指重啟 JVM 后,資料是否有效,默認為false -->
    <!-- timeToIdleSeconds 屬性:物件空閑時間(單位:秒),指物件在多長時間沒有被訪問就會失效,只對eternal為false的有效,默認值0,表示一直可以訪問 -->
    <!-- timeToLiveSeconds 屬性:物件存活時間(單位:秒),指物件從創建到失效所需要的時間,只對eternal為false的有效,默認值0,表示一直可以訪問 -->
    <!-- memoryStoreEvictionPolicy 屬性:快取的 3 種清除策略,因為快取區域是一定的,滿了之后就需要清除不需要的資料 -->
    <!-- 1. FIFO:first in first out (先進先出). 先快取的資料會先被清除-->
    <!-- 2. LFU:Less Frequently Used (最少使用).意思是一直以來最少被使用的,快取的元素有一個 hit 屬性,hit 值最小的將會被清除 -->
    <!-- 3. LRU:Least Recently Used(最近最少使用). (ehcache 默認值).快取的元素有一個時間戳,當快取容量滿了,而又需要騰出地方來快取新的元素的時候,那么現有快取元素中時間戳離當前時間最遠的元素將被清除 -->

    <defaultCache eternal="false"
                  maxElementsInMemory="1000"
                  overflowToDisk="false"
                  diskPersistent="false"
                  timeToIdleSeconds="0"
                  timeToLiveSeconds="600"
                  memoryStoreEvictionPolicy="LRU"/>

    <!-- name: Cache的名稱,必須是唯一的(ehcache會把這個cache放到HashMap里)-->
    <cache name="userCache"
           eternal="false"
           maxElementsInMemory="100"
           overflowToDisk="false"
           diskPersistent="false"
           timeToIdleSeconds="0"
           timeToLiveSeconds="300"
           memoryStoreEvictionPolicy="LRU"/>
</ehcache>

  1. 在持久化類的映射檔案中指定快取策略

User.hbm.xml:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.god23bin.demo.domain.entity.User" table="user">
        <!-- 指定快取策略 -->
        <cache usage="read-only"/>
		...
    </class>
</hibernate-mapping>

測驗二級快取:

    @Test
    public void testSecondLevelCache() {
        Session session1 = HibernateUtil.getSession();
        Session session2 = HibernateUtil.getSession();
        try {
            System.out.println("第一個 Session 去查詢資料并封裝成物件");
            User user1 = session1.get(User.class, new Integer("2"));
            System.out.println("用戶名:" + user1.getName());

            System.out.println("第二個 Session 去查詢同一資料并封裝成物件");
            User user2 = session2.get(User.class, new Integer("2"));
            System.out.println("用戶名:" + user1.getName());
        } catch (Exception e) {
            System.out.println("查詢User資料失敗!");
            e.printStackTrace();
        } finally{
            // 關閉 Session 物件
            HibernateUtil.closeSession();
        }
    }

控制臺輸出:

五月 09, 2023 11:18:31 下午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
第一個 Session 去查詢資料并封裝成物件
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.password as password3_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
用戶名:god23bin
第二個 Session 去查詢同一資料并封裝成物件
用戶名:god23bin

總結

本篇文章主要講了基本的 CRUD 操作,都是通過 Session 去操作的,根據一個持久化類的型別以及一個唯一標識進行相關操作,然后講了 Hibernate 中的物件的狀態,有 4 種,分別是瞬時、持久、游離、洗掉,

接著說了 Hibernate 的懶加載,有利于降低資料庫的開銷,當然快取也是,除了加快我們的訪問速度,也降低了直接訪問資料庫的開銷,快取就兩種,一級和二級,一級默認是開啟的,二級需要引入相關的依賴項,然后進行配置,開啟二級快取,配置快取策略,

這里附上整個專案的目錄結構,便于對照:

image-20230509234027184

以上,就是本篇的內容,這些都應該掌握,咱們下期再見,

最后的最后

希望各位螢屏前的靚仔靚女們給個三連!你輕輕地點了個贊,那將在我的心里世界增添一顆明亮而耀眼的星!

咱們下期再見!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/552102.html

標籤:其他

上一篇:【Visual Leak Detector】核心原始碼剖析(VLD 2.5.1)

下一篇:返回列表

標籤雲
其他(158772) Python(38125) JavaScript(25413) Java(18025) C(15225) 區塊鏈(8263) C#(7972) AI(7469) 爪哇(7425) MySQL(7175) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5871) 数组(5741) R(5409) Linux(5338) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4570) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1972) 功能(1967) Web開發(1951) HtmlCss(1935) python-3.x(1918) 弹簧靴(1913) C++(1913) xml(1889) PostgreSQL(1875) .NETCore(1860) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Hibernate 基本操作、懶加載以及快取

    上一篇咱們介紹了 Hibernate 以及寫了一個 Hibernate 的工具類,快速入門體驗了一波 Hibernate 的使用,我們只需通過 Session 物件就能實作資料庫的操作了。

    現在,這篇介紹使用 Hibernate 進行基本的 CRUD、懶加載以及快取的知識。 ......

    uj5u.com 2023-05-11 07:32:24 more
  • 【Visual Leak Detector】核心原始碼剖析(VLD 2.5.1)

    使用 VLD 記憶體泄漏檢測工具輔助開發時整理的學習筆記。本篇對 VLD 2.5.1 原始碼做記憶體泄漏檢測的思路進行剖析。 ......

    uj5u.com 2023-05-11 07:32:18 more
  • 34基于Java的學生選課系統或學生課程管理系統

    基于java的學生課程管理系統,基于java的學生選課系統,javaWeb的學生選課系統,學生成績管理系統,課表管理系統,學院管理系統,大學生選課系統設計與實作,網上選課系統,課程成績打分。 ......

    uj5u.com 2023-05-11 07:32:13 more
  • 最佳實踐:路徑路由匹配規則的設計與實作

    本文設計并實作了一種專用于路徑路由匹配的規則,以一種簡單而通用的方式描述一組路徑的特征,來簡化這種場景路由描述難度,讓小白可以快速學習并上手。 ......

    uj5u.com 2023-05-11 07:25:44 more
  • 文盤Rust —— rust連接oss | 京東云技術團隊

    物件存盤是云的基礎組件之一,各大云廠商都有相關產品。這里跟大家介紹一下rust與物件存盤交到的基本套路和其中的一些技巧。 ......

    uj5u.com 2023-05-10 10:44:00 more
  • Java的抽象類 & 介面

    抽象類:在子類繼承父類時,父類的一些方法實作是不明確的(父類對子類的實作一無所知)。這時需要使父類是抽象類,在子類中提供方法的實作。

    介面(interface)技術主要用來描述類具有什么功能,而并不給出每個功能的具體實作。 ......

    uj5u.com 2023-05-10 10:38:48 more
  • 【11個適合畢設的Python可視化大屏】用pyecharts開發拖拽式可視

    你好,我是@馬哥python說,一枚10年程式猿。 一、效果演示 以下是我近期用Python開發的原創可視化資料分析大屏,非常適合畢設用,下面逐一展示:(以下是截圖,實際上有動態互動效果哦) 以下大屏均為@馬哥python說的個人原創,請勿轉載。 1.1 影視劇分析大屏 1.2 豆瓣電影分析大屏A ......

    uj5u.com 2023-05-10 10:27:16 more
  • 【11個適合畢設的Python可視化大屏】用pyecharts開發拖拽式可視

    你好,我是@馬哥python說,一枚10年程式猿。 一、效果演示 以下是我近期用Python開發的原創可視化資料分析大屏,非常適合畢設用,下面逐一展示:(以下是截圖,實際上有動態互動效果哦) 以下大屏均為@馬哥python說的個人原創,請勿轉載。 1.1 影視劇分析大屏 1.2 豆瓣電影分析大屏A ......

    uj5u.com 2023-05-10 10:25:24 more
  • Java的抽象類 & 介面

    抽象類:在子類繼承父類時,父類的一些方法實作是不明確的(父類對子類的實作一無所知)。這時需要使父類是抽象類,在子類中提供方法的實作。

    介面(interface)技術主要用來描述類具有什么功能,而并不給出每個功能的具體實作。 ......

    uj5u.com 2023-05-10 10:24:35 more
  • C語言快速入門教程1快速入門 2指令 3條件選擇

    快速入門 什么是C語言? C是一種編程語言,1972年由Dennis Ritchie在美國AT & T的貝爾實驗室開發。C語言變得很流行,因為它很簡單,很容易使用。今天經常聽到的一個觀點是--"C語言已經被C++、Python和Java等語言所取代,所以今天何必再去學習C語言"。我很不贊同這種觀點。 ......

    uj5u.com 2023-05-10 10:23:23 more