Hibernate緩存研究

来源:http://www.cnblogs.com/mstk/archive/2017/02/03/6363351.html
-Advertisement-
Play Games

1. 什麼是緩存? 資料庫的緩存指的是應用程式和物理數據源之間的數據。即把物理數據源的數據複製到緩存。有了緩存,可以降低應用程式對物理數據源的訪問頻率,從而提高效率。緩存的介質一般是記憶體,也可以是硬碟。 Hibernate的緩存有三種類型:一級緩存、二級緩存和查詢緩存。 2. 一級緩存 一級緩存即S ...


1. 什麼是緩存?

資料庫的緩存指的是應用程式和物理數據源之間的數據。即把物理數據源的數據複製到緩存。有了緩存,可以降低應用程式對物理數據源的訪問頻率,從而提高效率。緩存的介質一般是記憶體,也可以是硬碟。

Hibernate的緩存有三種類型:一級緩存、二級緩存和查詢緩存。

2. 一級緩存

一級緩存即Session緩存,由Session自動進行管理,不需要程式進行干預。一級緩存根據對象的ID進行載入和緩存。如下麵的代碼:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Course c = (Course) session.get(Course.class, 1);
        System.out.println("Name:" + c.getName());
        c = (Course) session.get(Course.class, 1);
        System.out.println("Name:" + c.getName());
        tx.commit();
        session.close();

    }

運行結果:

Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Name:電腦原理
Name:電腦原理

第1次查詢時生成了SQL語句,並將查詢出來的對象放在一級緩存裡面,第2次查詢時,在一級緩存裡面直接找到了這個對象,就不需要再次生成SQL語句了。

再看一個例子:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Course c = (Course) session.get(Course.class, 1);
        System.out.println("Name:" + c.getName());
        tx.commit();
        session.close();
        
        session = sessionFactory.openSession();
        tx = session.beginTransaction(); 
        c = (Course) session.get(Course.class, 1);
        System.out.println("Name:" + c.getName());
        tx.commit();
        session.close();
    }

由於一級緩存是Session級別的緩存,所以Session關閉以後,一級緩存也就不存在了,第2次查詢也要生成SQL語句:

Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Name:電腦原理
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Name:電腦原理

 3. 二級緩存

二級緩存即SessionFactory緩存,和一級緩存類似,也是根據對象的ID進行載入和緩存,區別就在於一級緩存只在Session內有效,而二級緩存在SessionFactory內有效。在訪問某個ID的對象時,先到一級緩存裡面去找,如果沒有找到就到二級緩存裡面去找。二級緩存包括EHCache,OSCache,SwarmCache和JBossCache等。這裡以EHCache作為例子。

二級緩存需要程式進行管理。首先,配置Maven下載相關的Jar,在pom文件裡面添加:

        <dependency> 
            <groupId>org.hibernate</groupId> 
            <artifactId>hibernate-ehcache</artifactId> 
            <version>4.1.0.Final</version> 
        </dependency>

        <dependency>  
            <groupId>net.sf.ehcache</groupId>  
            <artifactId>ehcache</artifactId>  
            <version>2.8.3</version>  
        </dependency>

創建EHCache配置文件ehcache.xml:

<ehcache>
    <diskStore path="E:\Eclipse\MyWorkspace\Cache"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="true"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
    />
    <cache name="com.hzhi.course.entity.Course"
        maxElementsInMemory="10000"
        eternal="true"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
    />
</ehcache>

defaultCache是預設的設置,下麵一個cache指明瞭對哪一個類進行二級緩存。裡面設置了最大緩存的對象數量,是否永久有效、最大空閑秒數、最大生存秒數、記憶體滿時是否寫到硬碟,寫到硬碟的路徑等等。

修改需要緩存的類的hbm文件:

    <class name="com.hzhi.course.entity.Course" table="clas">
        <cache usage="read-only"/>
                ......
    </class>

usage設置了併發訪問策略,一般設置成read-only。

修改applicationContext.xml中的SessionFactory的配置,增加二級緩存的一些屬性:

    <!-- SessionFactory -->
     <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" >
            <ref local="dataSource"/>
        </property>
        <!-- 配置Hibernate的屬性 -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.connection.isolation">8</prop>
                <!-- 二級緩存 -->
                <prop key="hibernate.cache.use_second_level_cache">false</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>                
                <prop key="hibernate.cache.provider_configuration_file_resource_path">WEB-INF/ehcache.xml</prop>                
            </props>
        </property>
     ......
</bean>

運行下麵的例子:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Course c = (Course) session.get(Course.class, 1);
        System.out.println("Name:" + c.getName());
        tx.commit();
        session.close();
        
        session = sessionFactory.openSession();
        tx = session.beginTransaction(); 
        c = (Course) session.get(Course.class, 1);
        System.out.println("Name:" + c.getName());
        tx.commit();
        session.close();
    }

結果:

Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Name:電腦原理
Name:電腦原理

雖然關閉了Session,但是二級緩存仍然存在,所以只生成了一次SQL語句。

下麵的例子:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Query query = session.createQuery("from Course");  
        Iterator iter = query.iterate();  
        while(iter.hasNext()){  
               System.out.println(((Course)iter.next()).getName());  
        }
        tx.commit();
        session.close();
        
        session = sessionFactory.openSession();
        tx = session.beginTransaction(); 
        query = session.createQuery("from Course");  
        iter = query.iterate();  
        while(iter.hasNext()){  
               System.out.println(((Course)iter.next()).getName());  
        }
        tx.commit();
        session.close();
    }

結果:

Hibernate: 
    select
        course0_.ID as col_0_0_ 
    from
        clas course0_
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
電腦原理
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
電腦網路
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
資料庫原理
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
C語言
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
大學英語A
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Java
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Linux
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
高等數學
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
語文
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
大學物理
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
軟體工程
Hibernate: 
    select
        course0_.ID as col_0_0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程

當使用Query的list()方法時,只生成一次SQL語句查詢出所有的對象,使用iterate()方法時,會先得到所有對象的ID,然後根據每個ID生成一次SQL語句查詢。第二個Session裡面使用的也是iterate()方法,首先生成一次SQL語句,得到ID,然後根據ID查找對象,由於開啟了二級緩存,在二級緩存裡面找到了對象,所以就直接輸出了,並沒有再根據每個ID生成SQL語句。

不論是一級緩存還是二級緩存,都只能緩存對象,不能緩存屬性的值。下麵的例子:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Query query = session.createQuery("select c.name from Course c");   
        List<String> names = query.list();  
        for(Iterator iter = names.iterator(); iter.hasNext();){  
            String name = (String) iter.next();  
            System.out.println(name);  
        }  
        System.out.println("----------");  
        query = session.createQuery("select c.name from Course c");   
        names = query.list();  
        for(Iterator iter = names.iterator(); iter.hasNext();){  
            String name = (String) iter.next();  
            System.out.println(name);  
        } 
        System.out.println("----------"); 
        tx.commit();
        session.close();

    }

運行結果:

Hibernate: 
    select
        course0_.NAME as col_0_0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------
Hibernate: 
    select
        course0_.NAME as col_0_0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------

雖然開啟了二級緩存,但是查詢的結果不是對象,是屬性,所以並沒有緩存,第2次查詢仍然生成了查詢語句。要解決這個問題,就需要查詢緩存。

3. 查詢緩存

在配置了二級緩存的基礎上,可以設置查詢緩存,在SessionFactory的設置裡面加上一行:

<prop key="hibernate.cache.use_query_cache">true</prop>

即打開了查詢緩存。查詢緩存也是SessionFactory級別的緩存,在整個SessionFactory裡面都是有效的。

關閉二級緩存,運行下麵的例子,在Query後面添加setCacheable(true)打開查詢緩存:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Query query = session.createQuery("select c.name from Course c");  
        query.setCacheable(true);  
        List<String> names = query.list();  
        for(Iterator iter = names.iterator(); iter.hasNext();){  
            String name = (String) iter.next();  
            System.out.println(name);  
        }  
        System.out.println("----------");  
        query = session.createQuery("select c.name from Course c");  
        query.setCacheable(true);  
        names = query.list();  
        for(Iterator iter = names.iterator(); iter.hasNext();){  
            String name = (String) iter.next();  
            System.out.println(name);  
        } 
        System.out.println("----------"); 
        tx.commit();
        session.close();

    }

結果:

Hibernate: 
    select
        course0_.NAME as col_0_0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------

由於兩次查詢的HQL語句是一致的,所以只生成一次SQL語句。但是如果把第二次查詢改一下:

        System.out.println("----------"); 
        query = session.createQuery("select c.name from Course c where c.id > 5");  
        query.setCacheable(true);  
        names = query.list();  
        for(Iterator iter = names.iterator(); iter.hasNext();){  
            String name = (String) iter.next();  
            System.out.println(name);  
        } 
        System.out.println("----------"); 

結果:

Hibernate: 
    select
        course0_.NAME as col_0_0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------
Hibernate: 
    select
        course0_.NAME as col_0_0_ 
    from
        clas course0_ 
    where
        course0_.ID>5
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------

由於HQL語句變了,所以第二次也生成了SQL語句。

查詢緩存可以緩存屬性,也可以緩存對象,但是當緩存對象時,只緩存對象的ID,不會緩存整個對象。下麵的例子:

    @Override
    public void testCache() {
        // TODO Auto-generated method stub
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();  
        Query query = session.createQuery("from Course");
        query.setCacheable(true);
        List<Course> list = query.list();
        for (int i=0; i<list.size(); i++){
            System.out.println(list.get(i).getName());  
        }
        System.out.println("----------"); 
        tx.commit();
        session.close();
        
        session = sessionFactory.openSession();
        tx = session.beginTransaction();        
        query = session.createQuery("from Course"); 
        query.setCacheable(true);
        list = query.list();
        for (int i=0; i<list.size(); i++){
            System.out.println(list.get(i).getName());  
        }
        System.out.println("----------"); 

        tx.commit();
        session.close();
    }

 結果:

Hibernate: 
    select
        course0_.ID as ID0_,
        course0_.NAME as NAME0_,
        course0_.COMMENT as COMMENT0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
Hibernate: 
    select
        course0_.ID as ID0_0_,
        course0_.NAME as NAME0_0_,
        course0_.COMMENT as COMMENT0_0_ 
    from
        clas course0_ 
    where
        course0_.ID=?
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------

由於開了查詢緩存,沒有開二級緩存,雖然使用的是list()方法一次查詢出了所有的對象,但是查詢緩存只緩存了對象ID,沒有緩存整個對象。所以在第2個Session裡面"from Course"這個HQL由於和前面的相同,並沒有生成SQL語句,但是由於沒有開二級緩存,沒有緩存整個對象,只能根據每個ID去生成一次SQL語句。雖然兩次用的都是list()方法,但是第一次是生成SQL語句去一次查詢出所有的對象,而第二次是根據查詢緩存裡面的ID一個一個的生成SQL語句。

如果同時打開查詢緩存和二級緩存,第2個Session裡面就不用再根據ID去生成SQL語句了:

Hibernate: 
    select
        course0_.ID as ID0_,
        course0_.NAME as NAME0_,
        course0_.COMMENT as COMMENT0_ 
    from
        clas course0_
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------
電腦原理
電腦網路
資料庫原理
C語言
大學英語A
Java
Linux
高等數學
語文
大學物理
軟體工程
----------

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • "ABP入門系列目錄——學習Abp框架之實操演練" "源碼路徑:Github LearningMpaAbp" 完成了簡單的增刪改查和分頁功能,是不是覺得少了點什麼? 是的,少了許可權管理。既然涉及到了許可權,那我們就細化下任務清單的功能點: 登錄的用戶才能查看任務清單 用戶可以無限創建任務並分配給自己, ...
  • 泛型不同參數類型生成的對象是相互獨立的。 //如 Tuple ts; Tuple to; //ts to 是兩個類型的對象。 很多時候,我們希望實現 to = ts 這種操作,為什麼?因為看上去它應該如此。 為了達到這個目的,就要解決“泛型參數轉換的問題”,這個問題的知識點是in out 泛型變體。... ...
  • lambda 傳遞ref參數有個語法bug,必須要顯式書寫參數類型。 //如 delegate bool FuncType(ref int num); FuncType func1; func1 = num => true; //錯 func1 = (ref num) => true;//錯 fun... ...
  • 上一篇在C++中反射調用.NET(一)中,我們簡單的介紹瞭如何使用C++/CLI並且初步使用了反射調用.NET程式集的簡單方法,今天我們看看如何在C++與.NET程式集之間傳遞複雜對象。 ...
  • python爆破定長密碼的腳本 ...
  • 指針與地址的加減 摘自 "http://http://www.cnblogs.com/haore147/p/3647231.html" 如上,a是一個一維數組,數組中有5個元素,所以 a的類型是數組指針;ptr是一個int 型的指針,ptr的類型是整型指針 。 1. &a + 1:取數組a 的首地址 ...
  • 四、填色 color 函數有三個參數。第一個參數指定有多少紅色,第二個指定有多少綠色,第三個指定有多少藍色。比如,要得到車子的亮紅色,我們用 color(1,0,0),也就是讓海龜用百分之百的紅色畫筆。 這種紅色、綠色、藍色的混搭叫做RGB(Red,Green,Blue)。因為紅綠藍是色光上的三原色 ...
  • 開發Python的環境有很多,原來已經在vs2013上面搭建好python的開發環境了,但是vs2013每次啟動都占太多記憶體(太強大了吧),這下出了vs code,既輕量又酷炫,正好拿來試一試開發python,點擊visual studio code1.9安裝教程 下麵直接上搭建Python環境步驟 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...