在配置文件中hibernate這個前綴可以省略不寫
如:<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
可寫爲<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
當我們的類名或屬性名與數據庫中的關鍵字衝突時,我們可以修改表中的字段名,也可以在映射文件
中加上反引號(`)在tab鍵上方,這時會當作字符串處理;或修改對應的表名稱
如:在oracle中user是一個關鍵字
<class name="User" table="`user`"> 或 <class name="User" table="tuser">
<property name="name" column="tname"/> 如這種
</class>
在配置文件中如果沒有指定table、column則hibernate會按默認執行,即表名與類名相同,字段名
與屬性名相同.
如果要求不允許有相同的name,則可以加上: unique="true"如下
<property name="name" unique="true"/>
對於下面這句代碼
User user = (User) session.get(User.class, id);
我們可以這樣理解
由於Session可以管理多個數據庫表所對應的多個實體對象,如果查詢id爲1的實體對象,
Session.get方法需要知道從哪個數據庫表中查詢id爲1的記錄,所以,除了給get方法傳遞所
要查詢的實體對象的id值外,還必須給get方法傳遞實體對象的類型,get方法才能知道去哪個
數據庫表中進行查詢
通過學習,我們可以發現通過session去查詢數據庫有很大的侷限性,它只能通過id去查詢,而
在現實使用中,我們的需求肯定不只這些.這時我們就需要通過hql完成查詢,hql是通過query創建
的:Query query = session.createQuery(hql);
以往的sql是查表,而這裏的hql是查詢對象
還有一種比hql更方便的查詢方式:Criteria,這也是由session創建的:
Criteria crit = session.createCriteria(Class clazz);
使用 命名參數 替換?
如:String hql = "from User as user where user.name=?";
query = session.createQuery(hql);
query.setString(0, name);//下標從0開始,跟jdbc不同
可通過命名參數修改爲
String hql = "from User as user where user.name=:name";需要加上一個冒號
query = session.createQuery(hql);
query.setString(name, "xyls");
這樣做就可以避免因爲失誤造成錯誤
實現分頁
query.setFirstResult(0);//從哪一條開始取
query.setMaxResults(10);//取多少條記錄
好處:跨數據庫,可移植,不論用哪一種數據庫,都可以通過此種方式,hibernate中通過方言類生成分頁語句
oracle用rowNormal
mysql用limit
sqlserver用top
要注意單向關聯與雙向關聯的關係
多對多關係(如:teacher-student),在操作和性能方面都不太理想,所以多對多的映射使用較少,
實際使用中最好轉換成一對多的對象模型,Hibernate會爲我們創建中間關聯表,轉換成兩個一對多的關係.
多對一的關係使用的最多
在學習Hibernate如何處理對象之間的關聯關係的底層細節時,可以從兩個方面去考慮:
.如何將對象之間的關聯關係保存到數據庫中
.如何檢索出關聯的對象
List存儲是有序的,而Set是無序的
<set name="emps">
<key column="depart_id"/>
<one-to-many class="Employee"/>
</set>
<list name="emps">
<key column="depart_id"/>
<!-- 下面這列不需要程序代碼與之對應,這是hibernate的需要 ,進行排序-->
<list-index column="order_col"/>
<one-to-many class="Employee"/>
</list>
bag標籤與list是相對應的,使用bag將不會進行排序了,可用下面的代碼替換上面的
表結構中不會多出order_col這一列
<bag name="emps">
<key column="depart_id"/>
<one-to-many class="Employee"/>
</bag>
下面是使用Map的形式
<map name="emps">
<key column="depart_id"/>
<map-key type="string" column="name"/>
<one-to-many class="Employee"/>
</map>
下面是使用數組的形式,數組存儲也是有序的,使用很少
<array name="emps">
<key column="depart_id"/>
<index column="array_col"/>
<one-to-many class="Employee"/>
</array>
我們在hibernate中常使用Set
List集合類型在有些一對多關聯關係中可能會很有用,例如:在論壇的版面管理中,將會涉及到
版面的上移/下移等操作,這就需要在版面集合中維護順序,用List集合類型就能很好的解決這個問題.
hibernate爲了完成懶加載的功能,將所有的集合類都重寫了一遍,如果我們進行強制類型轉換,
運行時會報異常.
***級聯(cascade)和關係維護(inverse):
hibernate默認對關聯屬性不進行實際的操作,通過配置級聯可以實現
級聯cascade:用來說明當對主對象進行某種操作時是否對其關聯的從對象也作類似的操作
一般對 多對一,多對多不設置級聯,在一對一,一對多中設置級聯
如:<set name="emps" cascade="save-update">//cascade有很多可選用的值
<key column="depart_id"/>
<one-to-many class="Employee"/>
</set>
**hibernate缺省情況下是維護關聯關係的inverse="false" **
inverse:是否放棄維護關聯關係(在java中兩個對象產生關聯關係時,對數據庫表的影響),
在一對多和多對多的集合定義中使用,inverst="true"表示該對象不維護關聯關係,該屬性的值一般在
使用有序集合時設置成false(hibernate缺省值是false).
一對多維護關聯關係就是更新外鍵,
多對多維護關聯關係就是在中間表中增刪記錄.(兩端都告訴,會報異常,可通過放棄關係維護避免)
注:配置成一對一的對象不維護關聯關係
inverse屬性只會在集合中出現,如Set,List,array,Map,不同於cascade
如:<set name="emps" inverse="true">//效率會更高一些,不會產生update語句,一端不會考慮多端
<key column="depart_id"/>
<one-to-many class="Employee"/>
</set>
注:inverse不允許在有序的集合中使用,如:List,數組等 因爲inverse端放棄維護關聯關係,有序集合
就不會再去記憶插入進來的數據的順序
hibernate不允許多的一端放棄維護關聯關係
繼承關係映射:
在一張表中實現
<discriminator column="type" type="int"/>//鑑別器,用來區別不同的子類,應放在id屬性下面
type="string"是默認的
如:<subclass name="Skiller" discriminator-value="1">
<property name="skill"/>
</subclass>
<subclass name="Sales" discriminator-value="2">
<property name="sell"/>
</subclass>
discriminator-value="*"用來區分
特有的字段不能加上非空約束
每個子類對應一張表,效率低,但是在關係模型上更合理
<joined-subclass name="Skiller" table="skiller">
<key column="emp_id"/>
<property name="skill"/>
</joined-subclass>
<joined-subclass name="Sales" table="sales">
<key column="emp_id"/>
<property name="sell"/>
</joined-subclass>
另一種情況:還需要鑑別器,單獨一張表處理sales,效率得到了提升
<discriminator column="type" type="int"/>
<subclass name="Skiller" discriminator-value="1">
<property name="skill"/>
</subclass>
<subclass name="Sales" discriminator-value="2">
<join table="sales">
<key column="emp_id"/>
<property name="sell"/>
</join>
</subclass>
如果有異常,可以通過刪除數據庫完成操作,因爲之前會有三張表
每個類獨立映射:不再提取公共類,不需要關聯查詢,每個具體類一張表
(混全使用"一個類繼承體系一張表"和"每個子類一張表"),需要更換主鍵生成策略hilo,不再需
要鑑別器,操作時報異常,需要刪除相關表,或刪除數據庫,重建
如果主表是抽象的,加一個屬性abstract="true",就不會產生Employee表了
<id name="id">
<generator class="hilo"/>
</id>
<union-subclass name="Skiller" table="skiller">
<property name="skill"/>
</union-subclass>
<union-subclass name="Sales" table="sales">
<property name="sell"/>
</union-subclass>
注意一條原則:表的數目不要超過類的數目,表越多關聯查詢就越多,效率就越低