歡迎使用我的 在線工具

          小D

          讀歷史、看小說、寫程序都是我所愛。技術不好,頭腦不靈光,靠的是興趣。
          隨筆 - 35, 文章 - 25, 評論 - 13, 引用 - 0
          數據加載中……

          Hibernate的筆記

          1、 left outer join 左外連接:
          左外連接的查詢結果集中包括指定左表(主表)中的所有行,
          * 而不僅僅是連接列的所有行。如果左表的某行在右表(從表)中沒有找到匹配的行,則結果
          ???? ? * 集中的右表的相對的位置為 NULL

          2、關于hibernate.hbm2ddl.auto
          ? <property name="hibernate.hbm2ddl.auto">update</property>
          ???? 將這個屬性設為 update 只有我們發生修改的時候才會重新創建表 否則不會被覆蓋掉(未理解)

          ,在SessionFactory創建時,自動檢查數據庫結構,或者將數據庫schema的DDL導出到數據庫。使用

          create-drop時,在顯式關閉SessionFactory時,將drop掉數據庫schema.
          ??????? 例如:我們將所有的表都刪除了當我們執行插入操作時,SessionFactory被創建那么會自動檢

          查數據庫scheme的DDL,建立數據表,并且會保留原來的數據,所以我們不用 Export 配置中的數據到數

          據庫,那樣會覆蓋掉所有的數據。

          3、?關于對象關系信息導出
          這里必須調用 configure 方法 否則會映射 properties 文件
          ??????? Configuration cfg = new Configuration().configure();??
          ??//用于導出用戶定義的 xml 配置信息,在數據庫中生成對應的Table
          ??SchemaExport export = new SchemaExport(cfg);
          ??export.create(true, true);

          4、* 測試lazy在class上的策略 這里默認為true
          我們在這里應當搞清session.get()和session.load()的區別
          方法load支持 lazy(在Session緩存中生成一個User的子類對象返回,只有當調用方法是才查詢) 如果

          不存在查詢的結果則拋異常
          ? ???session = HibernateUtil.getSession();
          ???tx = session.beginTransaction();
          ??????????? Classes c1 = (Classes)session.load(Classes.class, 1);
          ??????????? System.out.println("c1.getId()"+c1.getId());
          ??????????? System.out.println("c1.getName()"+c1.getName());
          這里不會發出sql語句,因為這里就采用lazy策略,所以這里采用了第三方的組件返回了一個,一個新的

          Classes 的實例(代理),只有當我們需要查詢屬性時才會發出算sql語句,在這里不會發出sql語句因為

          id 是我們輸入的。
          hibernate 支持的lazy 策略只在session的生命周期內有效。

          5、lazy在collection上的策略
          ?很顯然這些lazy都是默認的
          ????Classes c1 = (Classes)session.load(Classes.class, 1);
          ???//如果我們將集合上的lazy設為false,這里會發出兩條sql除了將要查詢的

          普通屬性查出來外,還會將非普通屬性
          ???//將集合上的lazy設為extra和true是一樣的
          ???System.out.println("c1.name= " + c1.getName());
          ???//沒有發出sql 但是會生成一個 persistent 的set作為代理
          ??????????? Set students = c1.getStudents();
          ??????????? for(Iterator it = students.iterator();it.hasNext();){
          ??????????? ?Student s = (Student)it.next();
          ??????????? ?System.out.println("student.name= " + s.getName());
          ??????????? }
          ??????????? //System.out.println("student.number= " + student.size());
          ??????????? //這里會將所有的數據讀取出來并生成對象存放在set中
          ??????????? /*這里Classes的lazy策略只對普通的屬性有關,而collection的lazy策略才對
          ???????????? * collection對象生效*/
          *測試在標簽上的lazy 策略和集合上的lazy策略一樣。
          6、one2one
          <class name="org.n2535.hibernate.Person" table="t_person">
          ? <id name="id">
          ? <!-- 這里表示了Person的主鍵是作為一個外鍵關聯了IdCard的主鍵 -->
          ???? <generator class="foreign">
          ???? <!-- 表示主鍵的生成是根據 屬性 idCard 的 id -->
          ?????? <param name="property">idCard</param>
          ???? </generator>
          ? </id>
          ? <property name="name" />
          ? <!-- 表示了Person與Idcard是一對一的關系 默認為根據主鍵加載對象(主鍵關聯) -->
          ??????? <!-- constrained(約束) (可選) 表明該類對應的表對應的數據庫表,
          ?????????????? 和被關聯的對象所對應的數據庫表之間,通過一個外鍵引用對主鍵進行約束。
          ????????????? 而且它們之間的約束條件為true
          ??????? 在這里默認了兩者的級聯操作,否則的話一方的主鍵就為空沒有任何意義了 -->
          ? <one-to-one name="idCard" constrained="true"/>
          </class>
          關于idCard的xml配置可以用
          ?? <!-- 默認為主鍵關聯 即加載cardNo 時根據其主鍵將 關聯的Person表中 主鍵相同的 元組

          取出
          ?????? 默認的抓取策略為 Join? -->
          ? <one-to-one name="person"/>

          當然也可以不用。

          7、extends
          ?<!-- 測試每個具體的類映射一種表,這里Animal應該是抽象的,所以不應該被生成出來,將

          abstract="true"-->
          <class name="Animal" abstract="true">

          ? <id name="id">
          ???? <generator class="assigned"/>
          ? </id>
          ? <!-- 此處不需要鑒別器,因為每個具體的類都生產了一張表 -->
          ? <property name="name" />
          ? <property name="sex" />
          ? <union-subclass name="Pig" table="t_pig">
          ? <property name="weight"/>
          ? </union-subclass>
          ?
          ? <union-subclass name="Bird" table="t_bird">
          ? <property name="height"/>
          ? </union-subclass>
          ?</class>?

          <!-- 測試單表繼承映射 -->
          <class name="Animal" table="t_animal" lazy="false">

          ? <id name="id">
          ???? <generator class="native"/>
          ? </id>
          ? <!-- discriminator 鑒別器,用來識別不同的子類 -->
          ? <discriminator column="type" type="string"/>
          ?
          ? <property name="name" />
          ? <property name="sex" />
          ? <!-- Pig -->
          ? <!-- discriminator-value的默認是完整的類名 -->
          ? <subclass name="Pig" discriminator-value="P">
          ??? <property name="weight"/>
          ? </subclass>
          ?
          ? <!-- Bird -->
          ? <subclass name="Bird" discriminator-value="B">
          ??? <property name="height"/>
          ? </subclass>
          ?</class>

          8、component 組件映射測試
          ?component類不是一個實體類,在hibernate中的實體是指的 一個Pojo+一個映射文件
          ??component類是一個輔助類
          ?? component 組件映射
          ? <component name="contact" class="org.n2535.hibernate.Contact">
          ??? <property name="email"/>
          ??? <property name="address"/>
          ??? <property name="zipCode"/>
          ??? <property name="contactTel"/>
          ? </component>

          9、復合主鍵
          因為主鍵是不可重復的,所以在復合主鍵的類中我們實現了Serializable接口,
          和hashcode、equals方法,能夠確保主鍵的唯一性。
          ?<!-- 復合主鍵映射我們也可以認為是一種 component 組件映射的一種? -->
          ?? <composite-id name="pk">
          ?? <key-property name="productYear"/>
          ?? <key-property name="productMonth"/>
          ?? </composite-id>
          ?? <property name="name"/>
          ?? <property name="factory"/>
          ?</class>?

          10、集合映射
          ??
          ? <set name="setValue" table="t_set_value">
          ? ?<key column="set_id"/>
          ? ?<element type="string" column="set_value"/>
          ? </set>
          ?
          ? <list name="listValue" table="t_list_value">
          ? ?<key column="list_id"/>
          ? ?<!-- 這里必須給出排序的索引,因為list是有序的(下同) -->
          ? ?<list-index column="list_index"/>
          ? ?<element type="string" column="list_value"/>
          ? </list>
          ?
          ? <array name="arrayValue" table="t_array_value">
          ? ?<key column="array_id"/>
          ? ?<list-index column="array_index"/>
          ? ?<element type="string" column="array_value"/>
          ? </array>
          ?
          ? <map name="mapValue" table="t_map_value">
          ? ?<key column="map_id"/>
          ? ?<map-key type="string" column="map_key"/>
          ? ?<element type="string" column="map_value"/>
          ? </map>

          11、關于Hibernate的鎖
          ?1)、悲觀鎖:先獲得數據庫的鎖的線程,知道該線程放棄提交,其他的線程將無法修改該數據

          (LockMode.UPGRADE :利用數據庫的for update子句加鎖。)
          2)、樂觀鎖:通常利用一個 version 的版本沖突來實現,實際上不是數據庫的鎖,一個線程的version

          必須大于數據庫中的version值才能被存儲,否則報錯。這樣提供了比悲觀鎖寬松的條件,只要 version

          大于數據庫中的version就可以被存儲,而不會因為是否死一個線程先獲得鎖,因為樂觀鎖根本就不是一

          種鎖。
          ? * 未使用悲觀鎖的時候,不同的操作可以訪問相同的數據,那么會造成數據的錯誤
          ? * 使用悲觀鎖的時候,可以避免這個問題
          可以不用顯示的調用,如果為調用update那么在提交的時候會自動的update,當第一個操作將數據鎖住

          的時候,(所有的其他訪問將被禁止)第二個select操作將會阻塞,知道第一個操作釋放了鎖,第二個

          對象的選擇操作會根據第一個對像的update的結果來讀取數據,如果兩個對象都從數據庫中讀取了相同

          的數據,那么第一次的update操作,將會被第二次的覆蓋,造成錯誤的數據。
          ?session.update(inv);
          ?要使用悲觀鎖請使用指定的數據庫的命令,或者使用hibernate中的配置。
          ? * 樂觀鎖采用的version的沖突機制,如果update的version小于或數據庫中的version
          ? * 將會產生錯誤插入失敗,一位update的限制條件是根據 主鍵和version 所以會失敗
          ? * 我們還能仿照 Hibernate 的樂觀鎖機制,用Jdbc實現樂觀鎖
          ?
          12、hibernate查詢語言hql?
          在hql中關鍵字不區分大小寫,但是屬性和類名區分大小寫

          1)、簡單屬性查詢【重要】
          ?* 單一屬性查詢,返回結果集屬性列表,元素類型和實體類中相應的屬性類型一致
          ?* 多個屬性查詢,返回的集合元素是對象數組,數組元素的類型和對應的屬性在實體類中的類型

          一致
          ?? 數組的長度取決與select中屬性的個數
          ?* 如果認為返回數組不夠對象化,可以采用hql動態實例化Student對象
          ?參見:SimplePropertyQueryTest.java?

          2)、實體對象查詢【重要】
          ?* N + 1問題,在默認情況下,使用query.iterate查詢,有可以能出現N+1問題
          ?? 所謂的N+1是在查詢的時候發出了N+1條sql語句
          ?? 1: 首先發出一條查詢對象id列表的sql
          ?? N: 根據id列表到緩存中查詢,如果緩存中不存在與之匹配的數據,那么會根據id發出相應的

          sql語句
          ?* list和iterate的區別?
          ??* list每次都會發出sql語句,list會向緩存中放入數據,而不利用緩存中的數據
          ??* iterate:在默認情況下iterate利用緩存數據,但如果緩存中不存在數據有可以能

          出現N+1問題
          ?參見:SimpleObjectQueryTest1.java/SimpleObjectQueryTest2.java
          ?
          3)、條件查詢【重要】?
          ?* 可以采用拼字符串的方式傳遞參數
          ?* 可以采用 ?來傳遞參數(索引從0開始)
          ?* 可以采用 :參數名 來傳遞參數
          ?* 如果傳遞多個參數,可以采用setParamterList方法
          ?* 在hql中可以使用數據庫的函數,如:date_format
          ?參見:SimpleConditionQueryTest.java ?
          ???
          4)、hibernate也支持直接使用sql進行查詢
          ?參見:SqlQueryTest.java

          5)、外置命名查詢
          ?* 在映射文件中采用<query>標簽來定義hql
          ?* 在程序中采用session.getNamedQuery()方法得到hql查詢串
          ?參見:Student.hbm.xml、NameQueryTest.java
          ?
          6)、查詢過濾器?
          ?* 在映射文件中定義過濾器參數
          ?* 在類的映射中使用這些參數
          ?* 在程序中啟用過濾器
          ?參見:Student.hbm.xml、FilterQueryTest.java
          ?
          7)、分頁查詢【重要】?
          ?* setFirstResult(),從0開始
          ?* setMaxResults,每頁顯示多少條數據
          ?參見:PageQueryTest.java
          ????
          8)、對象導航查詢,在hql中采用 . 進行導航【重要】
          ?參見:ObjectNavQueryTest.java
          ?
          9)、連接查詢【重要】
          ?* 內連
          ?* 外連接(左連接/右連接)?
          ?參見:JoinQueryTest.java
          ?
          10)、統計查詢【重要】
          ?參見:StatQueryTest.java
          ?
          11)、DML風格的操作(盡量少用,因為和緩存不同步)
          ?參見:DMLQueryTest.java

          13、Hibernate中的緩存
          ?1)、一級緩存
          session 中一級緩存的生命周期和session的相同
          由于load使用了session中的一級緩存 所以第二次的load 并不會發sql 因為在session的緩存中還存在

          相同的數據。
          由于get使用了session中的一級緩存 所以第二次的get 并不會發sql 因為在session的緩存中還存在相

          同的數據。
          ?? ?會發出查詢 id 的 sql(使用一級緩存才會發出) 但是不會發出查詢對象的 sql 因為Iterate

          查詢支持緩存。
          在save的時候會在緩存中保存一份當前對象的引用。
          session.clear();//全部清除
          2)、二級緩存
          ???? <!-- 指定二級緩存的提供者 -->
          ??? <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
          ??? <!-- 指定是否使用二級緩存 默認為true -->
          <property name="cache.use_second_level_cache">true</property>
          使用ehcache.xml這個配置文件來配置二級緩存。
          session 中二級緩存的生命周期和sessionFactory的相同,所以又稱為 sessionFactory 級緩存,二級

          緩存只能用于存儲實體。
          3)、三級緩存
          ??? <!-- 使用查詢緩存 默認為false-->
          ??? <property name="cache.use_query_cache">true</property>
          queryCache生命周期和sessionFactory的相同。
          但是在數據庫里面的數據改變的時候,queryCache中的對象失效。
          QueryCache的生命周期與session無關。
          Iterate 接口不支持 QueryCache。
          這里使用list 來查詢實體對象 并開啟了QueryCache 由于QueryCache 會存儲實體的主鍵值,而list 在

          查詢實體的時候不會使用緩存 所以list會使用QueryCache的實體的主鍵值 去查詢相應的,實體,由于

          它會現在緩存中查找實體對象 如果不存在則會發出sql到數據庫中查詢 這里沒有配置二級緩存 ,又重

          開了session所以在緩存中不存在實體對象 所以會根據在QueryCache 中的實體主鍵值發出sql到數據庫

          中查詢。
          因為開啟了二級緩存,QueryCache 會存儲查詢出來的實體的主鍵,而list會根據在QueryCache中的 主

          鍵值到二級緩存中查找相應的實體,所以不會發出sql(list接口不會使用一級緩存但是能夠利用這種方

          法使用QueryCache 和 二級緩存)。

          14、抓取策略
          ?1)、fetch = "select" 抓取策略 發兩個select語句;fetch = "join" 抓取策略 使用外連接

          查詢。
          2)、在集合中的抓取策略
          ??使用 load
          ? * fetch = "select" 抓取策略 發兩條sql
          ? * fetch = "join" 發一條sql 采用外連接查詢
          ?使用 HQL
          * fetch = "select" 抓取策略 發兩條sql 和加載對象方式一樣,每次每個實體的集合時會發sql
          * fetch = "subselect" 將會在查詢實體的集合時將所有查詢的實體的集合發一次sql 全部查詢出來
          3)、測試 batch – size
          ?batch-size="3"在集合中設置。

          ?

          posted on 2009-11-04 21:09 vagasnail 閱讀(310) 評論(0)  編輯  收藏 所屬分類: Java框架


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 应城市| 遂宁市| 闸北区| 义马市| 兴城市| 宁乡县| 萨迦县| 博野县| 十堰市| 揭西县| 云龙县| 合江县| 色达县| 麻城市| 扎鲁特旗| 宜昌市| 平凉市| 清水河县| 木兰县| 灵石县| 鲜城| 凭祥市| 伊春市| 正定县| 安化县| 调兵山市| 苗栗市| 云浮市| 和硕县| 枣阳市| 六枝特区| 九龙县| 庆安县| 黔江区| 治多县| 天祝| 图片| 军事| 夏河县| 福海县| 奎屯市|