Mybatis

来源:http://www.cnblogs.com/tonghun/archive/2017/05/27/6914634.html
-Advertisement-
Play Games

一概述 1.什麼是Mybatis? ⑴Mybatis是Apache的一個開源項目,原名為ibatis,移植到google code後改名為Mybatis,目前遷移到了Github。 ⑵Mybatis是一個支持定製化SQL、存儲過程以及高級映射的優秀持久層框架,避免了幾乎所有的JDBC代碼、手動設置參 ...


 

一概述

1.什麼是Mybatis?

⑴Mybatis是Apache的一個開源項目,原名為ibatis,移植到google code後改名為Mybatis,目前遷移到了Github。

⑵Mybatis是一個支持定製化SQL、存儲過程以及高級映射的優秀持久層框架,避免了幾乎所有的JDBC代碼、手動設置參數以及獲取結果集的過程。

2.Mybatis與Hibernate對比

兩者的主要區別在於封裝程度:

⑴Hibernate封裝程度較高,表現為可以自動建立映射關係,即查詢結果自動封裝為實體類對象,而Mybatis必須手動為結果指明映射的實體類。

⑵Hibernate封裝了SQL語句,而Mybatis中的SQL語句需要程式員編寫。

⑶Hibernate能夠創建表,Mybatis不能創建與修改表,只能修改表中的數據。

⑷正因為Hibernate封裝程度較高,獲得同樣的結果所需代碼比Mybatis複雜,執行速度慢,Web應用中速度是至關重要的,所以Hibernate正逐漸被Mybatis取代。

3.Mybatis體繫結構,由上至下:

⑴API介面:

Mybatis的頂層,Mybatis提供給開發人員的用於操作資料庫的入口,主要是一些對象中的方法。

⑵數據處理層:

頂層的API介面被調用以後,觸發數據處理層,該層具體負責SQL查找、SQL解析、SQL執行、結果映射。

⑶基礎支撐層:

為整個框架的運行提供了基礎性質的支撐,主要有配置載入、連接管理、事務管理、緩存管理。

4.Mybatis基本執行過程:

啟動時載入配置文件,為映射文件中的每一個SQL語句創建一個MappedStatement對象,通過API介面調用SQL語句,系統根據id找到對應的MappedStatement對象,解析成SQL語句,連接資料庫執行,最後將查詢結果映射成屬性或者對象。

5.配置文件:

<configuration>
    <!--載入包含資料庫連接四要素的屬性文件 -->
    <properties  resource="dbConnection.properties"/>
    <!--為映射文件中的類起一個別名,這樣在映射文件中可以省去書寫全限定性類名,直接使用別名 -->
    <typeAliases>
             <typeAlias  type="com.mybatis.beans.demo01.Student" alias="Student"/>
             <!--<package  name="com.mybatis.beans.demo01" /> -->
    </typeAliases>
    <!--配置環境,可以有多個環境,比如測試環境,發佈環境,default選擇使用的環境。環境指的是資料庫管理方面的信息,比如數據源、事務-->
    <environments  default="development">
       <environment  id="development">
           <!--表示採用JDBC預設的事務管理器,項目開發時用DataSourceTransactionManger-->
           <transactionManager type="JDBC" />
           <!--採用Mybatis自帶的資料庫連接池,項目開始時通常使用C3P0或者DBCP -->
           <dataSource  type="POOLED">
                      <!--從載入的屬性文件中讀取資料庫連接四要素 -->
                      <property  name="driver" value="${jdbc.driver}" />
                      <property  name="url" value="${jdbc.url}" />
                     <property  name="username" value="${jdbc.username}" />
                     <property  name="password" value="${jdbc.password}" />
           </dataSource>
       </environment>
    </environments>
    <!--載入映射文件 -->
    <mappers>
           <mapper  resource="com/mybatis/beans/demo01/Student.xml" />
    </mappers>
</configuration>

配置文件主要包含:

⑴資料庫連接四要素通常放在屬性文件中,便於更改。為每一個環境都創建一個屬性文件,key相同,當需要載入某個環境時,只需要將總環境的預設值設為該環境的id。從屬性文件中讀取數據的基本語法格式:${key}。

⑵<typeAliases>用於為類指定一個別名:

①<typeAlias  type="com.mybatis.beans.demo01.Student" alias="Student"/>:為全限定性類名指定一個別名,在映射文件中使用該別名替代全限定性類名,使代碼簡潔。

②<package  name="com.mybatis.beans.demo01" />:指定包名,在沒有註解的情況下,系統採用非限定性類名作為別名,首字母可以小寫。

⑶<environments>:配置文件中可以有多個環境,分別用於不同的用途,default屬性指定當前使用的環境。

⑷<environment>:主要包含事務管理器、數據源等。

⑸<mappers>:將映射文件載入到配置文件中。

6.映射文件:

<mapper  namespace="student">
      <insert  id="insertStudent">
               insert  into tb_student(name,score)values(#{name},#{score})
                      ----------在數據插入完成後獲取插入數據的id------------
              <selectKey  resultType="int"keyProperty="id">
                              select@@identity
              </selectKey>
      </insert>
      <delete  id="deleteStudent">delete from tb_student  whereid=#{?}</delete>
                      ------------------------------模糊查詢-------------------------------
      <select  id=""resultType="xxxx">select name from xxx where name like '%'#{}'%'</select>
<mapper>

⑴映射文件用於設定欄位與屬性的映射關係。

⑵namespace:命名空間,即名稱存在的範圍,用於區分不同映射文件中同名的SQL。

⑶id:在同一個映射文件中不可重覆,用於在程式中調用該SQL。

⑷parameterType:當參數類型是實體類時,可以直接使用配置文件中的別名。

⑸select:有返回值,返回值可以是屬性,也可以是實體類對象,因此必須指定單行數據返回值類型resultType,以便系統按照該類型返回查詢結果。

⑹Mybatis為常見的java類型設定了別名,別名大小寫不敏感,即大小寫作用相同。基本數據類型的別名在前面加下劃線,如_int,其他常用類型的別名就是首字元小寫後的非限定性類名,如String的別名是string,由於大小寫不敏感,也可以寫成String。

⑺語法介紹:

①#{屬性名}:獲取對象屬性值;

②#{xxx}:用作占位符,可以是任意合法字元,用於參數不是實體類對象時取得參數的值。

⑻模糊查詢語法格式:‘%’#{xxx},為了避免系統將占位符視作普通字元處理,占位符放在單引號或者雙引號外面,與單引號或者雙引號之間不使用任何連接。

7.預設封裝時,採用反射機制,封裝時根據欄位名調用set方法初始化對象,因此表中的欄位名必須與實體類中對應的屬性名相同,如果欄位名與屬性名不同,那麼該屬性無法被初始化。

屬性名與欄位名不一致時的解決方案:

①使用別名:通過別名將查詢結果的欄位名修改為屬性名,缺點是每一次查詢時都需要創建別名。

②使用resultMap:採用Hibernate的處理方式,手動在欄位與屬性之間建立映射:

<resultMap  type="studentResultMap"id="studentMap">
       <id  column="id" property="sid" />
       <result  column="name" property="sname" />
</resultMap>

8.SqlSessionFactory

⑴相當於Hibernate中的SessionFactory對象,主要負責創建SqlSession對象。創建初始化過程耗費大量系統資源,並且線程安全,因此將對象設定為應用級的,即在整個應用範圍採用單例模式。

⑵創建:

InputStream  input=Resources.getResourceAsStream("文件的類路徑");//基於路徑創建輸入流
SqlSessionFactory  factory=new  SqlSessionFactoryBuilder().build(input);

輸入流工廠對象創建完畢後自動關閉,不需要手動關閉。

9.SqlSession

⑴Mybatis持久化操作的核心,線程不安全,應該設置為多例的,即一個線程一個。

⑵創建:

SqlSession  sqlSession=factory.openSession();//使用openSession的無參形式時,自動關閉自動提交

⑶主要方法:

①sqlSession.close():關閉sqlSession對象,如果未回滾,回滾。

⑷dirty:一個框架底層的boolean值,主要用於判斷當前緩存中內容與資料庫中內容是否相同,相同為false,不同為true,數據提交或者回滾時需要判斷該值。

10.使用log4j技術輸出日誌信息。

 

二 Mapper動態代理

1.如果Dao介面的方法名與映射文件中SQL語句的id相同,那麼根據方法名就可以找到對應的SQL語句,從而省去將方法與SQL語句綁定的過程。需要做兩點:方法名與id相同,命名空間為Dao介面的全限定性類名。

2.怎麼在java代碼中獲取操作對象?

由於採用Mapper動態代理,省去了Dao實現層,只剩下Dao介面,而Dao介面無法實例化,那麼就根據該介面創建一個代理對象,作為操作對象:

IDao dao=sqlSession.getMapper(IDao.class);

3.基本原理

利用JDK動態代理創建了一個代理對象,該代理對象在Dao方法與映射文件SQL語句間建立了映射關係,所以稱作
MapperProxy。

 

三多條件查詢

1.什麼是多條件查詢?

根據多個條件進行查詢,叫做多條件查詢,就是查詢時傳入多個參數,稱作多參數查詢更準確。

2.多參數查詢問題產生的原因?

同時向SQL語句傳入多個參數,就出現了一個對應問題,傳入的參數與SQL語句中的哪個占位符對應,因此產生了多參數查詢問題。Mybatis中進行持久化操作的方法只允許存在一個傳入SQL語句的參數。

3.解決方法

⑴手動封裝:為每一個參數設定一個key值,將多個key/value保存到Map對象中,將Map對象作為參數傳入SQL語句,在SQL語句中通過 #{key}獲取參數value的值。

⑵自動封裝:方法定義時設定key。

Student  selectStudentByIndex(@Param("name")String name,@Param("score") double score);

⑶高版本多參數查詢不支持索引。

 

四 #在映射文件中的用法

1.#{attr}:當參數是實體類對象時,獲取屬性值;

2.#{?}:當參數是基本數據類型或者字元串時,用作占位符,獲取參數的值,{}內部可以是任意合法字元,一般用屬性名。

3.#{key}:當參數是Map集合時,通過key值獲取value的值。

 

五動態SQL

1.什麼是動態SQL?

根據傳入的參數選擇性執行SQL語句,這一過程叫做動態SQL.

2.動態SQL中用到的字元:

<if>\<where>\<choose  when  otherwise>\<foreach>。

3.<where if>:

從多個過濾條件中選擇若幹個。

⑴基本格式:

<where>
       <if  test="scoreKey>0">score>#{scoreKey}</if>
       <if  test="nameKey!=null &amp;nameKey!=''">and name like"%"#{nameKey}"%"</if>
</where>

⑵test用來指明判斷條件,其中使用key值;為了完成組合,除第一個<if>標簽外,其他標簽的內容都必須以連接符開頭,如and,or。

⑶映射文件是一個XML文檔,而在XML文檔中不允許使用> >= < <= &,必須使用對應的實體替換。

4.<where choose when otherwise>:

從多個條件中選擇第一個為真的執行。

基本格式:

<where>
     <choose>
           <when  test="nameKey!=null and nameKey!=''"> name like"%"#{nameKey}"%"</when>
           <when  test="scoreKey > 0">score>#{scoreKey}</when>
           <otherwise>1=2</otherwise>
     </choose>
</where>

5.<where foreach>:遍歷列表。

⑴基本格式:

<select  id="selectStudentsByArray"resultType="student">
       select  id,name,score from tb_student
        <where>
               <if  test="array.length>0">
                                    id in
                    <foreach  collection="array"item="myid" open="(" close=")"separator=",">
                                   #{myid}
                    </foreach>
               </if>
        </where>
</select>

⑴當參數類型是數組時,collection值為array;參數類型是List時,collection值為list。

⑵item表示遍歷的子對象,集合或者數組中一個元素。

⑶open/close/separator:用於拼湊JDBC中的(a,b,c)的列表形式。

 

六實體關聯查詢

1.什麼是實體關聯查詢?

兩個實體間存在關聯關係,即引用關係,通過一個實體查詢關聯的實體,這就是實體關聯查詢。

2.關聯關係查詢時必須手動地為欄位建立與屬性的映射關係。

3.一對多關聯查詢:

映射文件的編寫:

<resultMap  id="countryMapAlone"type="Country">
          <id  property="cid" column="cid" />
          <result  property="cname" column="cname" />
          <collection  property="ministers" ofType="Minister"select="ministerSelect"column="cid" />
</resultMap>
<select  id="selectCountryByIdAlone" resultMap="countryMapAlone">
          selectc  id,cname from tb_country where cid=#{cid}
</select>
<select  id="ministerSelect" resultType="Minister">
          select   mid,mname,countryId from tb_minister where countryId=#{cid}
</select>

在<collection>標簽中:

⑴ofType:指明集合中的每一個元素的類型。

⑵select屬性用來指明從載入方的查詢語句。

⑶column屬性指明將主載入方查詢結果的哪個欄位傳入從載入方的查詢語句中。

4.多對一關聯查詢:

映射文件編寫:

<select  id="selectMinisterById"resultMap="ministerMap">
            select  mid,mname,countryId from tb_minister where mid=#{id}
</select>
<resultMap id="ministerMap"type="com.mybatis.entityRelation.m2o.Minister">
           <id  property="mid" column="mid" />
           <result  property="mname" column="mname" />
           <result  property="countryId" column="countryId" />
           <association  property="country"javaType="com.mybatis.entityRelation.m2o.Country"
                          select="selectCountry"column="countryId" />
</resultMap>
<select  id="selectCountry" resultType="com.mybatis.entityRelation.m2o.Country">
                          selectc  id,cname from tb_country where cid=#{countryId}
</select>

5.自關聯:

⑴什麼是自關聯?

兩個實體類除了一個關聯屬性外其他屬性完全相同,將兩個實體當做一個實體處理,這樣關聯關係就轉化為了自關聯。

⑵把自關聯看做一對多雙向關聯。

⑶查找自身及其子對象:

<select  id="selectNewsLabelsById"resultMap="">
             select  id,name,pid from tb_newslabel where id=#{id}
</select>
<resultMap  id="" type="newsLabel">
            <id  property="id" column="id" />
<result  property="name" column="name" />
           <result  property="pid" column="pid" />
           <collection  property="childNewsLabels" ofType="newsLabel"select="selectChild"column="id" />
</resultMap>
<select  id="selectChild" resultType="newsLabel">
            select  id,name,pid from tb_newslabel where pid=#{id}
</select>

6.多對多關聯查詢:

⑴將多對多關聯看做兩個一對多關聯,一方是原有兩方中的任一方,多方是中間表,中間表有兩個外鍵,分別引用其他兩張表的主鍵。

⑵多對多關聯查詢多採用表連接查詢,同時查詢三張表,因為這種操作方式簡單。

⑶多表聯合查詢分別查詢:

<select  id="selectStudentByIdAlone" resultMap="aloneMap">
             select  sid,sname from tb_studentc where sid=#{sid}
</select>
<resultMap  id="aloneMap"type="com.mybatis.entityRelation.m2m.Student">
            <id  property="sid" column="sid" />
            <result  property="sname" column="sname" />
            <collection  property="courses" ofType="com.mybatis.entityRelation.m2m.Course"
                         select="selectCourse"column="sid" />
</resultMap>
<select  id="selectCourse"resultType="com.mybatis.entityRelation.m2m.Course">
    select  cid,cname from tb_course where cid in (select course_id from tb_mid where student_id=#{sid})//採用臨時表
</select> 

 

七延時載入

1.什麼是延時載入?

載入主載入方時,不立即載入從載入方,而是根據設定延遲載入從載入方。

2.延時載入針對的關聯查詢時的從載入方,設定從載入方的載入時機。

3.Mybatis中載入從載入方的幾種方式:

⑴直接載入:主載入方載入完畢後,立即載入從載入方,未開啟延時載入時採用該載入方式。

⑵侵入式延遲:將從載入方當做主載入方的詳情,訪問主載入方的詳情時,載入從載入方。

⑶深度延遲:只有在訪問從載入方對象時才載入從載入方。

4.延時載入的設置:

⑴預設情況下,延遲載入是關閉的,主載入方載入完畢後立即載入從載入方。在配置文件中開啟延時載入:

<settings>
           <setting  name="lazyLoadingEnabled" value="true" />
</settings>

⑵開啟延遲載入以後,預設採用深度延遲。

⑶如需要採用侵入式延遲:

<settings>
           <setting  name="lazyLoadingEnabled" value="true" />
           <setting  name="aggressiveLazyLoading" value="true" />
</settings>

 

八緩存

1.緩存是記憶體中的臨時存儲區,用來存放從資料庫中載入的數據,目的是為了提高查詢速度。

2.緩存內容的來源:SQL查詢從資料庫中載入的數據。

3.緩存內容的類型:封裝的實體類對象與分散的屬性值。

4.Mybatis中用兩種緩存:一級緩存,二級緩存。

5.無論一級緩存,還是二級緩存,只在同一namespace中可見,對其他namespace的查詢不可見。

6.緩存的存儲格式:緩存以Map集合的形式存儲內容,key是SQL id與SQL語句的組合,value是從資料庫中載入的內容。

7.無論一級緩存,還是二級緩存,緩存查找依據都是SQLid與SQL語句,即根據SQL id與SQL語句查找緩存中是否具有相同的內容。

8.一級緩存與二級緩存持有的是同一對象的記憶體地址,執行增刪改操作,將會清空一級緩存,即銷毀引用地址指向的對象,同時預設清空二級緩存。清空的是緩存Map集合的value值,保留key值。

9.一級緩存:

⑴一級緩存:SqlSession級的,緩存中的內容只能在同一個SqlSession內部共用,生命周期與SqlSession相同。

⑵一級緩存是預設的緩存,無法關閉,也無法通過設置改變屬性,即只能採用預設的方式,不能自定義。

⑶sqlSession關閉意味著Session對象銷毀,一級緩存釋放持有的引用地址,而不是銷毀對象。

10.Mybatis提供了兩種二級緩存方案:內置二級緩存與第三方二級緩存Ehcache。

⑴二級緩存預設情況下是開啟的。

⑵二級緩存不會主動載入對象,要想將對象載入到二級緩存中,必須在命名空間下開啟二級緩存:<cache/>,該命名空間下所有查詢操作的結果都會被保存到二級緩存中。

⑶二級緩存的關閉:

①應用範圍關閉:<setting  name="cacheEnabled" value="true" />;

②命名空間範圍關閉:註銷掉命名空間下的<cache/>.

③SQL範圍關閉:<select  useCache="false"/>

⑷二級緩存使用原則:

①避免多個namespace操作同一張表:二級緩存是基於namespace的,不同namespace對二級緩存的操作是隔離的,相當於每一方都把資料庫中的數據讀取到記憶體中,各自獨立操縱,這樣當一方的操作同步到資料庫以後,另一方還在操作資料庫中改變了的數據,造成幻讀。

②不要在關聯關係表上執行增刪改操作:不同的表對應不同的namespace,同一張表可能同時被多個namespace操作,導致幻讀。

③查詢多於增刪改時使用二級緩存:增刪改清空緩存,消耗系統資源。

⑸開啟內置二級緩存:

①序列化實體類:應用內置二級緩存的實體類必須序列化。

②<cache/>:在指定命名空間使用二級緩存。

⑹使用Ehcache第三方緩存Ecache:

①導入架包;

②<cache type="org.mybatis.caches.ehcache.EhcacheCache" />:在命名空間指定使用Ehcache二級緩存;

③導入Ehcache配置文件ehcache.xml,放在類路徑下。

⑺預設情況下,執行增刪改操作會清空二級緩存,如果不希望某個增刪改操作清空二級緩存,可以在映射文件<insert/delete/update>標簽下設置,將flushCache設為false。由於一級緩存與二級緩存引用的是同一對象,如果不希望清空二級緩存,不能在一級緩存持有引用地址的情況下執行增刪改操作。

 

九註解

1.註解是在java類文件中添加註解以替代映射文件的註冊方式。

2.為了充分發揮框架的功能,Mybatis推薦使用映射文件,不建議使用註解。

3.常用註解:

⑴@Insert()/@Delete()/Update()。

⑵@Select(value=""):使用註解查詢時可以省略結果類型。

⑶@SelectKey(statement = "select@@identity",resultType=Integer.class,keyProperty = "id", before =false):獲取剛插入數據的主鍵值,必須與插入註解聯合使用。

⑷在配置文件中註冊Dao介面:

①<mapper  class=""/>:通過Dao類註冊。

②<package  name="Dao類所在的包"/>:通過包名註冊,可以同時註解該包下的多個Dao介面。

 


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

-Advertisement-
Play Games
更多相關文章
  • Big Nerd Ranch是美國一家專業的移動開發技術培訓機構。本書主要以其Android訓練營教學課程為基礎,融合了幾位作者多年的心得體會,是一本完全面向實戰的Android編程指南。全書共34章,詳細介紹了8個Android 應用。通過這些精心設計的應用,讀者可掌握很多重要的理論知識和開發技巧 ...
  • 最近在做iOS系統通訊錄備份到伺服器,並且可以從伺服器中下載備份文件恢復到手機的功能,部分實現細節記錄如下。 將iphone系統通訊錄生成.vcf文件 運行後系統沙盒Document目錄下會生成contacts.vcf文件,上傳至伺服器即可。 通訊錄恢復: 從伺服器下載contents.vcf文件, ...
  • 用as開發過程中遇見問題app閃退 log如下圖: 解決: File—Settings: 點擊Apply—OK重新運行即可 ...
  • Shader學習筆記 例子: Mesh Filter : 存儲一個Mesh(網格,模型的網格,就是模型的由哪些三角面組成,組成一個什麼樣子的模型,三角面的一些頂點信息) Mesh Renderer:用來渲染一個模型的外觀,就是樣子, 按照 mesh給它皮膚,給它顏色 通過Material(材質)控制 ...
  • 一、簡介 1. 定位的實際應用場景: 導航:去任意陌生的地方 周邊:找餐館、找酒店、找銀行、找電影院等 2. 涉及技術: Core Location 框架:用於地理定位。(單純的定位,不需要顯示地圖) 常用類:以CL首碼開頭 CLLocation:(結構體類型)經緯度 CLLocationManag ...
  • 今天將項目從ionic2 升級為ionic3 ,ionic serve 運行在網頁上無任何錯誤。 但是將項目打包成為android apk 卻一直卡在啟動頁面 白屏,進不去的情況。後來在android studio 控制台看到這個錯誤提示:Uncaught SyntaxError Use of co ...
  • 一,效果圖。 二,工程圖。 三,代碼。 RootViewController.h RootViewController.m ...
  • 《NoSQL精粹》為考慮是否可以使用和如何使用NoSQL資料庫的企業提供了可靠的決策依據。它由世界軟體開發大師和軟體開發“教父”Martin Fowler與Jolt生產效率大獎圖書作者Pramod J. Sadalage共同撰寫。書中全方位比較了關係型資料庫與NoSQL資料庫的異同;分別以Riak、 ...
一周排行
    -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# ...