五、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 關閉整個連接配接,動作太大)