天天看點

我的hibernate學習筆記(之三)

 五、Hibernate 主鍵政策( 上面的步驟三的一部分)  

    <id><generator class=“主鍵政策” /></id>  

    主鍵:在關系資料庫中,主鍵用來辨別記錄并保證每條記錄的唯一性( 一般可保證全資料庫唯一) 。必須滿足以下條件: 

        1)不允許為空。 

        2)不允許主鍵值重複。 

        3)主鍵值不允許改變。 

    1.自然主鍵:以有業務含義的字段為主鍵,稱為自然主鍵。 

        優點:不用額外的字段。 

        缺點:當業務需求發生變化時,必須修改資料類型,修改表的主鍵,增加了維護資料庫的難度。 

    2.代理主鍵:增加一個額外的沒有任何業務含義的一般被命名為ID 的字段作為主鍵。 

        缺點:增加了額外字段,占用部分存儲空間。 

        優點:提高了資料庫設計的靈活性。 

    Hibernate用對象辨別(OID) 來區分對象: 

        Student stu = (Student)session.load(Student.class,101); //這代碼加載了OID 為101 的Student 對象 

       Hibernate推薦使用代理主鍵,是以Hibernate 的OID 與代理主鍵對應,一般采用整數型,包括:short 、int 、long 。

    1、主鍵生成政策:(Hibernate 支援多種主鍵生成政策)  

    generator節點中class 屬性的值: 

      1) assigned:assigned :由使用者自定義ID ,無需Hibernate 或資料庫參與。是<generator> 元素沒有指定時的預設生成政策。 

           <id name="id" column="id"><generator class="assigned"/></id>

      2) hilo:通過hi/lo( 高/ 低位) 算法生成主鍵,需要另外建表儲存主鍵生成的曆史狀态( 這表隻需要一個列和高位初始值) 。 

         hi/lo算法産生的辨別隻在一個特定的DB 中是唯一的。所有資料庫都可用。 

         如果同一個資料庫裡多張表都需要用;可以建多張主鍵表,也可以共用同一字段,但最好是用同一張主鍵表的不同字段。 

           <id name="id" column="id">

<generator class="hilo">

            <!--指定高位取值的表--> 

               <param name="table">high_val</param>

             <!--指定高位取值的列--> 

               <param name="column">nextval</param>

             <!--指定低位最大值,當取到最大值是會再取一個高位值再運算--> 

               <param name="max_lo">5</param>          

</generator>

</id>

      3) sequence:采用資料庫提供的Sequence 機制。 

         Oracle,DB2等資料庫都提供序列發生器生成主鍵,Hibernate 也提供支援。 

<generator class="sequence">

                  <param name="sequence">序列名</param> 

              </generator>

      4) seqhilo:功能同hilo ,隻是自動建表儲存高位值。主鍵生成的曆史狀态儲存在Sequence 中。 

         隻能用于Oracle 等支援Sequence 的資料庫。 

           <id name="id" column="id"><generator class="hilo">

               <param name="sequence">high_val_seq</param>

  <param name="max_lo">5</param>

           </generator></id>

      5) increment:主鍵按數值順序遞增。 

         作用類型:long,short,int 

         使用場景:在沒有其他程序同時往同一張表插資料時使用,在cluster 下不能使用 

      6) indentity:采用資料庫提供的主鍵生成機制。特點:遞增。(Oracle 不支援)  

         通常是對DB2,Mysql, MS Sql Server, Sybase, Hypersonic SQL(HSQL) 内置的辨別字段提供支援。 

         傳回類型:long,short, int   

           <id name="id" column="id"><generator class="identity"/></id>

         注:使用MySql 遞增序列需要在資料庫建表時對主健指定為auto_increment 屬性。用Hibernate 建表則不需要寫。 

           (oid int primary key auto_increment) 

      7) native:由Hibernate 根據底層資料庫自行判斷采用indentity, hilo 或sequence 中的一種。 

         是最通用的實作,跨資料庫時使用。Default.sequence 為hibernate_sequence 

           <id name="id" column="id"><generator class="native"/></id>

      8) foreign:由其他表的某字段作為主鍵,通常與<one-to-one> 聯合使用;共享主健( 主鍵與外鍵) ,兩id 值一樣。 

           <id name="id" column="id" type="integer">

<generator class="foreign">

                    <param name="property">car</param> 

                 </generator>

      9) UUID: 

         uuid.hex:由Hibernate 基于128 位唯一值産生算法生成十六進制數( 長度為32 的字元串--- 使用了IP 位址) 。 

         uuid.string:與uuid.hex 一樣,但是生成16 位未編碼的字元串,在PostgreSQL 等資料庫中會出錯。 

         特點:全球唯一;ID 是字元串。 

      10)select:通過DB 觸發器(trigger) 選擇一些唯一主鍵的行,傳回主鍵值來配置設定主鍵 

      11)sequence-identity:特别的序列發生政策,使用DB 序列來生成值,通常與JDBC3 的getGenneratedKeys 一起用,使得在執行insert 時就傳回生成的值。Oracle 10g( 支援JDK1.4) 驅動支援這一政策。 

    2、複合主鍵政策 

       步驟一:建立資料庫表,設定聯合主鍵限制 

       步驟二:編寫主持久化類以及主鍵類;編寫主鍵類時,必須滿足以下要求: 

          1)實作Serializable 接口 

          2)覆寫equals 和hashCode 方法 

          3)屬性必須包含主鍵的所有字段 

       步驟三:編寫*.hbm.xml 配置檔案 

          <composite-id name="dogId" class="composite.vo.DogId">

            <key-property name="name" type="string"><column name="d_name"/></key-property>

            <key-property name="nick" type="string"><column name="d_nick"/></key-property>

          </composite-id>

六、Hibernate 的查詢方案( 應該熟悉各種查詢的使用方法) 

    1、利用Session 接口提供的load 方法或者get 方法 

    2、Hibernate 提供的主要查詢方法 

       1)Criteria Query(條件查詢) 的步驟: 

         (1)通過Session 來建立條件查詢對象Criteria 

            Criteria criteria = session.createCriteria(Course.class);

         (2)建構條件--- 建立查詢條件對象Criterion 

            Criterion criterion1 = Property.forName("id").ge(39);//通過Property 來建立 

            Criterion criterion2 = Restrictions.le("cycle", 5); //通過Restrictions 來建立 

         (3)查詢對象關聯條件 

            criteria.add(criterion1);

         (4)執行條件查詢 

            List<Course> courses = criteria.list();

       2)HQL(Hibernate Qurey Language)

         特點: 文法上與SQL 類似; 完全面向對象的查詢; 支援繼承、多态、關聯 

         (1) FROM子句 

             例如:查詢所有的學生執行個體 

             Query query=session.createQuery("from Student");

query.list();

         (2) SELECT子句 

             選擇哪些對象和屬性傳回到結果集 

          A、SELECT 語句後可以跟多個任意類型的屬性,傳回結果儲存在Object 類型的數組中 

             //A、B 、C 、都是查詢學生的姓名和年齡 

             Query query=session.createQuery("select stu.name,stu.age from Student as stu");

             List<Object[]> os=query.list();//傳回的Object 數組中有兩個元素,第一個是姓名,第二個是年齡 

          B、SELECT 語句後可以跟多個任意類型的屬性,傳回結果也可以儲存在List 中 

             Query query=session.createQuery ("select new List(stu.name,stu.age) from Student as stu");

             List<List> lists=query.list();

          C、SELECT 語句後可以跟多個任意類型的屬性,傳回結果也可以是一個類型安全的POJO 對象 

             Query query=session.createQuery

  ("select new Student(stu.name,stu.age) from Student as stu");

             List<Student> stuList=query.list();//注意:Student 類必須有Student(String,int) 的構造方法 

          D、SELECT 子句中可以使用聚集函數、數學操作符、連接配接 

             支援的聚集函數:avg 、sum 、min 、max 、count …. 

         (3) WHERE子句,限制傳回結果集的範圍 

         (4) ORDER BY子句,對傳回結果集進行排序 

       3)Native SQL(原生SQL 查詢)  

         可移植性差:資源層如果采用了不同的資料庫産品,需要修改代碼--- 非不得已,不推薦使用 

         步驟一:調用Session 接口上的createSQLQuery(String sql) 方法, 傳回SQLQuery 

         步驟二:在SQLQuery 對象上調用addEntity(Class pojoClass) // 設定查詢傳回的實體 

           例如:

SQLQuery query =session.createSQLQuery(“select * from student limit 2,10”)

                query.addEntity(Student.class);

                List<Student> stuList=query.list();

七、 Hibernate 對象的狀态 

    實體對象的三種狀态: 

    1) 暫态( 瞬時态)(Transient)--- 實體在記憶體中的自由存在,它與資料庫的記錄無關。 

        po在DB 中無記錄( 無副本) ,po 和session 無關( 手工管理同步)  

        如:

Customer customer = new Customer();

  customer.setName("eric");

        這裡的customer 對象與資料庫中的資料沒有任何關聯 

    2) 持久态(Persistent)--- 實體對象處于Hibernate 架構的管理中。 

        po在DB 中有記錄,和session 有關(session 自動管理同步)  

    3)遊離态( 脫管态)(Detached) 

        處于Persistent 狀态的實體對象,其對應的Session 執行個體關閉之後,那麼,此對象處于Detached 狀态。 

        po在DB 中有記錄,和session 無關( 手工管理同步)  

      無名态:po 處于遊離态時被垃圾回收了。沒有正本,隻有DB 中的副本。 

      po處于暫态時被垃圾回收了,則死亡。( 唯一可以死亡的狀态)  

    實質上,這三個狀态是:持久對象的正副本與同步的關系 

    原則:盡量使用持久态。 

    三态的轉換: 

        暫态---> 持久态 

            A.調用Session 接口上的get() 、load() 方法 

            B.調用Session 接口上的save() 、saveOrUpdate() 方法 

        持久态---> 暫态 

            delete();

        遊離态---> 持久态 

            update()、saveOrUpdate() 、lock(); 

            (lock不建議用,危險;肯定沒變化時用,有則用updata)  

        持久态---> 遊離态 

            evict()、close() 、clear()  

            (一般用evict ,隻關閉一個實體的連接配接;close 關閉整個連接配接,動作太大)