1.對象的狀態(tài)
Hibernate中對象的狀態(tài): 臨時/瞬時狀態(tài)壳澳、持久化狀態(tài)、游離狀態(tài)糊探。
1.1 臨時狀態(tài)
直接new出來的對象; 不處于session的管理;數(shù)據(jù)庫中沒有對象的記錄;
1.2 持久化狀態(tài)
當(dāng)調(diào)用session的save/saveOrUpdate/get/load/list等方法的時候钾埂,對象就是持久化狀態(tài)河闰。
處于持久化狀態(tài)的對象,當(dāng)對對象屬性進(jìn)行更改的時候褥紫,會反映到數(shù)據(jù)庫中!
特點(diǎn):
處于session的管理;
數(shù)據(jù)庫中有對應(yīng)的記錄;
1.3 游離狀態(tài)
不處于session的管理姜性;數(shù)據(jù)庫中有對應(yīng)的記錄;Session關(guān)閉后,對象的狀態(tài)髓考;
2. 一級緩存
1)Hibenate中一級緩存部念,也叫做session的緩存,它可以在session范圍內(nèi)減少數(shù)據(jù)庫的訪問次數(shù)氨菇! 只在session范圍有效儡炼! Session關(guān)閉,一級緩存失效查蓉!
2)當(dāng)調(diào)用session的save/saveOrUpdate/get/load/list/iterator方法的時候乌询,都會把對象放入session的緩存中。
3)Session的緩存由hibernate維護(hù)豌研, 用戶不能操作緩存內(nèi)容妹田; 如果想操作緩存內(nèi)容,必須通過hibernate提供的evit/clear方法操作鹃共。
特點(diǎn):
只在(當(dāng)前)session范圍有效鬼佣,作用時間短,效果不是特別明顯霜浴!
在短時間內(nèi)多次操作數(shù)據(jù)庫晶衷,效果比較明顯!
2.1 緩存相關(guān)幾個方法的作用
session.flush(); 讓一級緩存與數(shù)據(jù)庫同步
session.evict(arg0); 清空一級緩存中指定的對象
session.clear(); 清空一級緩存中緩存的所有對象
session.save():實體被納入session緩存阴孟,session計劃執(zhí)行sql晌纫,此時查詢不會有結(jié)果(無插入sql的執(zhí)行);
session.flush():session“清理”緩存,發(fā)送執(zhí)行sql永丝,但不提交事務(wù)缸匪,此時在同一session中執(zhí)行查詢可以查詢到結(jié)果(處于同一個數(shù)據(jù)庫會話,盡管該會話的事物尚未提交类溢,數(shù)據(jù)庫中無真實的數(shù)據(jù),此時查詢到的應(yīng)該是數(shù)據(jù)庫本身事務(wù)機(jī)制的緩存)露懒,但在另外的查詢中不會有結(jié)果(比如在native mysql中闯冷,因為不處于同一個數(shù)據(jù)庫會話中);
commit():發(fā)送執(zhí)行sql并提交事務(wù)懈词;事務(wù)完成
2.2 list與iterator查詢的區(qū)別
**list() **
一次把所有的記錄都查詢出來蛇耀,
會放入緩存,但不會從緩存中獲取數(shù)據(jù)
iterator
N+1查詢坎弯; N表示所有的記錄總數(shù)
即會先發(fā)送一條語句查詢所有記錄的主鍵(1)纺涤,
再根據(jù)每一個主鍵再去數(shù)據(jù)庫查詢(N)译暂!
會放入緩存,也會從緩存中取數(shù)據(jù)撩炊!
3.懶加載
當(dāng)用到數(shù)據(jù)的時候才向數(shù)據(jù)庫查詢外永,這就是hibernate的懶加載特性。
3.1 lazy 值
true 使用懶加載
false 關(guān)閉懶加載
extra (在集合數(shù)據(jù)懶加載時候提升效率)
在真正使用數(shù)據(jù)的時候才向數(shù)據(jù)庫發(fā)送查詢的sql拧咳;
如果調(diào)用集合的size()/isEmpty()方法伯顶,只是統(tǒng)計,不真正查詢數(shù)據(jù)骆膝!
3.2 get祭衩、load方法區(qū)別
get: 及時加載,只要調(diào)用get方法立刻向數(shù)據(jù)庫查詢
load:默認(rèn)使用懶加載阅签,當(dāng)用到數(shù)據(jù)的時候才向數(shù)據(jù)庫查詢掐暮。
3.3 懶加載異常
Session關(guān)閉后,不能使用懶加載數(shù)據(jù)政钟!如果session關(guān)閉后路克,使用懶加載數(shù)據(jù)報錯:org.hibernate.LazyInitializationException: could not initialize proxy - no Session
如何解決session關(guān)閉后不能使用懶加載數(shù)據(jù)的問題?
a.方式1: 先使用一下數(shù)據(jù)
dept.getDeptName();
b.方式2:強(qiáng)迫代理對象初始化
Hibernate.initialize(dept);
c.方式3:關(guān)閉懶加載
設(shè)置lazy=false;
d.方式4: 在使用數(shù)據(jù)之后锥涕,再關(guān)閉session衷戈!
4.組件映射與繼承映射
4.1 組件映射
類組合關(guān)系的映射,也叫做組件映射层坠!
注意:組件類和被包含的組件類殖妇,共同映射到一張表!
需求: 汽車與車輪
public class Car {
private int id;
private String name;
// 車輪
private Wheel wheel;
}
// 車輪
public class Wheel {
private int count;
private int size;
}
<hibernate-mapping package="cn.itcast.d_component">
<class name="Car" table="t_car">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name" length="20"></property>
<!-- 組件映射 -->
<component name="wheel">
<property name="size"></property>
<property name="count"></property>
</component>
</class>
</hibernate-mapping>
4.2 繼承映射
// 動物類
public abstract class Animal {
private int id;
private String name;
}
public class Cat extends Animal{
// 抓老鼠
private String catchMouse;
public String getCatchMouse() {
return catchMouse;
}
public void setCatchMouse(String catchMouse) {
this.catchMouse = catchMouse;
}
}
public class Monkey extends Animal {
// 吃香蕉
private String eatBanana;
public String getEatBanana() {
return eatBanana;
}
public void setEatBanana(String eatBanana) {
this.eatBanana = eatBanana;
}
}
4.2.1 所有子類映射到一張表
子類較多破花,且子類較為簡單谦趣,即只有個別屬性!
好處:因為使用一個映射文件座每, 減少了映射文件的個數(shù)前鹅。
缺點(diǎn):(不符合數(shù)據(jù)庫設(shè)計原則)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
繼承映射, 所有的子類都映射到一張表
-->
<hibernate-mapping package="cn.itcast.e_extends2">
<class name="Animal" table="t_animal">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 指定鑒別器字段(區(qū)分不同的子類) -->
<discriminator column="type_"></discriminator>
<property name="name"></property>
<!--
子類:貓
每個子類都用subclass節(jié)點(diǎn)映射
注意:一定要指定鑒別器字段峭梳,否則報錯舰绘!
鑒別器字段:作用是在數(shù)據(jù)庫中區(qū)別每一個子類的信息, 就是一個列
discriminator-value="cat_"
指定鑒別器字段,即type_字段的值
如果不指定葱椭,默認(rèn)為當(dāng)前子類的全名
-->
<subclass name="Cat" discriminator-value="cat_">
<property name="catchMouse"></property>
</subclass>
<!--
子類:猴子
-->
<subclass name="Monkey" discriminator-value="monkey_">
<property name="eatBanana"></property>
</subclass>
</class>
</hibernate-mapping>
4.2 每個類映射一張表(3張表)
一個映射文件捂寿,存儲所有的子類; 子類父類都對應(yīng)表孵运;
缺點(diǎn):表結(jié)構(gòu)比較負(fù)責(zé)秦陋,插入一條子類信息,需要用2條sql: 往父類插入治笨、往子類插入驳概!
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
繼承映射赤嚼, 每個類對應(yīng)一張表(父類也對應(yīng)表)
-->
<hibernate-mapping package="cn.itcast.e_extends3">
<class name="Animal" table="t_animal">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<!--
子類:貓 t_cat
key 指定_cat表的外鍵字段
-->
<joined-subclass name="Cat" table="t_cat">
<key column="t_animal_id"></key>
<property name="catchMouse"></property>
</joined-subclass>
<!-- 子類:猴子 t_monkey -->
<joined-subclass name="Monkey" table="t_monkey">
<key column="t_animal_id"></key>
<property name="eatBanana"></property>
</joined-subclass>
</class>
</hibernate-mapping>
4.3 每個子類映射一張表, 父類不對應(yīng)表(2張表)
所有的子類都寫到一個映射文件顺又;父類不對應(yīng)表更卒; 每個子類對應(yīng)一張表(推薦)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
繼承映射, 每個類對應(yīng)一張表(父類不對應(yīng)表)
-->
<hibernate-mapping package="cn.itcast.e_extends4">
<!--
abstract="true" 指定實體類對象不對應(yīng)表待榔,即在數(shù)據(jù)庫段不生成表
-->
<class name="Animal" abstract="true">
<!-- 如果用union-subclass節(jié)點(diǎn)逞壁,主鍵生成策略不能為自增長! -->
<id name="id">
<generator class="uuid"></generator>
</id>
<property name="name"></property>
<!--
子類:貓 t_cat
union-subclass
table 指定為表名, 表的主鍵即為id列
-->
<union-subclass name="Cat" table="t_cat">
<property name="catchMouse"></property>
</union-subclass>
<!-- 子類:猴子 t_monkey -->
<union-subclass name="Monkey" table="t_monkey">
<property name="eatBanana"></property>
</union-subclass>
</class>
</hibernate-mapping>