Hibernate
一、 基礎(chǔ)知識(shí)
① Hibernate是對(duì)象/關(guān)系映射(Object/Relation Mapping)的解決方案。
② Hibernate架構(gòu)
● POJO類
● hibernate.cfg.xml
● *.hbm.xml
● Hibernate應(yīng)用
二、 幾個(gè)重要的類
● Configuration類 (負(fù)責(zé)管理Hibernate的配置信息)
當(dāng)創(chuàng)建SessionFactory時(shí),Configuration實(shí)例可以指定使用哪一個(gè)映射文擋。應(yīng)用程序通常只是創(chuàng)建一個(gè)Configuration實(shí)例,并通過它創(chuàng)建一個(gè)SessionFactory實(shí)例。
● SessionFactory類 (負(fù)責(zé)創(chuàng)建Session實(shí)例)
它是線程安全的,可以被多線程調(diào)用以取得Session,而且構(gòu)造SessionFactory很消耗資源,所以多數(shù)情況下一個(gè)應(yīng)用中只初始化一個(gè)SessionFactory,為不同的線程提供Session。
● Session類
Session是Hibernate運(yùn)作的中心,對(duì)象的生命周期、事務(wù)的管理、數(shù)據(jù)庫的存取都與Session息息相關(guān)。Session不是線程安全的,多個(gè)執(zhí)行線程共享一個(gè)Session,將會(huì)發(fā)生數(shù)據(jù)共享而發(fā)生混亂問題。為了解決此問題,可以采用ThreadLocal變量,使用它可以有效隔離執(zhí)行所使用的數(shù)據(jù),也就避開了Session的多線程之間的數(shù)據(jù)共享問題。
如何調(diào)用hibernate API?
1、創(chuàng)建Configuration對(duì)象。(解析配置文件)
Configuration config = new Configuration();
2、通過Configuration創(chuàng)建Session Factory(線程安全的重量級(jí)組件)。
Config = config.configure(); //configure()方法會(huì)在CLASSPATH下尋找hibernate.cfg.xml
SessionFactory = config.buildSessionFactory();
3、通過SessionFactory創(chuàng)建Session會(huì)話對(duì)象。
Session session = sessionFactory.openSession();
4、通過Session取得事務(wù)對(duì)象。
Transaction trans = session.beginTransaction();
5、通過session與數(shù)據(jù)庫進(jìn)行會(huì)話。
session.save(object o); //增
session.delete(object o); //刪
session.update(object o); //改
session.get (Class clazz, Serializable id); //根據(jù)Id查找對(duì)象
session.createQuery(String sql); //自己拼HQL語言查找對(duì)象返回一個(gè)Query對(duì)象。
6、提交操作,結(jié)束事務(wù)。
Trans.commit();
7、關(guān)閉Session
session.close();
注:第一步和第二步一般放在靜態(tài)初始化代碼塊中執(zhí)行。
三、Hibernate中自帶ID的generator的含義:
1、identity:用于MySql數(shù)據(jù)庫。特點(diǎn):遞增
<id name="id" column="id">
<generator class="identity"/>
</id>
注:對(duì)于MySql數(shù)據(jù)庫使用遞增序列時(shí)需要在建表時(shí)對(duì)主鍵指定為auto_increment屬性。
2、sequence:用于Oracle數(shù)據(jù)庫
<id name="id" column="id">
<generator class="sequence">
<param name="sequence">序列名</param>
</generator>
</id>
3、native:跨數(shù)據(jù)庫時(shí)使用,由底層方言產(chǎn)生。
Default.sequence為hibernate_sequence
<id name="id" column="id">
<generator class="native"/>
</id>
注:使用native時(shí)Hibernate默認(rèn)會(huì)去查找Oracle中的hibernate_sequence序列。
如果Oracle中沒有該序列,連Oracle數(shù)據(jù)庫時(shí)會(huì)報(bào)錯(cuò)。
4、hilo:通過高低位合成id,先建表hi_value,再建列next_value。必須要
有初始值。
<id name="id" column="id">
<generator class="
<param name="table">high_val</param>
<param name="column">nextval</param>
<param name="max_lo">5</param>
</generator>
</id>
5、sequencehilo:同過高低位合成id,建一個(gè)sequence序列,不用建表。
<id name="id" column="id">
<generator class="
<param name="sequence">high_val_seq</param>
<param name="max_lo">5</param>
</generator>
</id>
6、assigned:用戶自定義id;
<id name="id" column="id">
<generator class="assigned"/>
</id>
7、foreign:用于一對(duì)一關(guān)系共享主健時(shí),兩id值一樣。
四、Hibernate類關(guān)系的處理:
1、One―to―One關(guān)系在數(shù)據(jù)庫中如何體現(xiàn),在JavaBean中如何體現(xiàn),在Hibernate中如何映射one-to-one關(guān)系。
1、數(shù)據(jù)庫中:一個(gè)表的外健對(duì)應(yīng)另一個(gè)表的主健,外健要加上Unique約束?;蛘呤莾蓚€(gè)表共享一個(gè)主健。
2、javaBean中:在JavaBean中增加一個(gè)屬性,即另外一個(gè)對(duì)象的引用,可以單向也可以雙向。
3、在hibernate中:
主健映射:都是one-to-one要用foreign生成策略。
外健映射:主表中用one-to-one,副表通過property-ref many-to-one
create table car_pk ( id number(10,0) not null, name varchar2(15), serial varchar2(30), manufacturer varchar2(50), producedate date, primary key (id) ); create table engine_pk ( id number(10,0) not null, model varchar2(20), manufacturer varchar2(50), producedate date, primary key (id) ); alter table engine_pk add constraint fk_engine_car_pk foreign key (id) references car_pk(id);
One-to-One PK主鍵映射 (詳見代碼)
Table car_pk
Id |
name |
serial |
manufacturer |
producedate |
|
|
|
|
|
Table engine_pk
Id |
model |
manufacturer |
producedate |
|
|
|
特點(diǎn):engine_pk 表的Id 與 car_pk表共享主鍵。
One-to-One FK外鍵映射 (詳見代碼)
Table car_pk
Id |
name |
serial |
manufacturer |
producedate |
|
|
|
|
|
Table engine_fk
Id |
carid |
model |
manufacturer |
producedate |
|
|
|
|
|
特點(diǎn):engine_fk表多了carid外鍵字段來維護(hù)與car_fk 表的關(guān)系。
建表語句如下:
create table engine_fk ( id number(10,0) not null, model varchar2(20) not null, manufacturer varchar2(50) not null, producedate date, carid number(10,0) unique, primary key (id) ); alter table engine_fk add constraint fk_engine_car_fk foreign key (carid) references car_fk(id);
2、Many-to-One關(guān)系在數(shù)據(jù)庫中如何體現(xiàn),在JavaBean中如何體現(xiàn),在
Hibernate中如何映射many-to-on關(guān)系。
1、數(shù)據(jù)庫中:一個(gè)表的主健對(duì)應(yīng)另一個(gè)表的外健。
2、javaBean中:一個(gè)對(duì)象包含另一個(gè)對(duì)象的一個(gè)引用,另一個(gè)對(duì)象包含這個(gè)對(duì)象的一組(集合,用set)引用。
3、在hibernate中:用set.key指定具體列。
在Set一端一定要寫inverse=“true”表示忽略集合一端的變化。
以Order類和Item類 的一對(duì)多關(guān)系為例子(詳見代碼):
Item
-id: Integer -product: String -amount: int -order: Order
- -
|
Order
-id: Integer -owner: String -phone: String -address: String -items: Set<Item> |
1 * |
小結(jié): 對(duì)象的關(guān)聯(lián)關(guān)系有一對(duì)一、一對(duì)多、多對(duì)一和多對(duì)多,其中多對(duì)一和一對(duì)多關(guān)系比較常見。
一對(duì)一關(guān)系有兩中方式:以主鍵關(guān)聯(lián)和以外鍵關(guān)聯(lián)。
一對(duì)多和多對(duì)一通常應(yīng)設(shè)置為雙向關(guān)聯(lián),并在“一”這一方設(shè)置inverse="true"(比如一個(gè)班級(jí)對(duì)應(yīng)多個(gè)學(xué)生,在班級(jí)這一邊設(shè)置inverse="true")。設(shè)置了inverse="true"這一端比較清閑,它把控制權(quán)交給了另一端。讓“多”這一端有控制權(quán)。
多對(duì)多 可以借助中間表來保存兩個(gè)實(shí)體之間的關(guān)系。
對(duì)象在Hibernate中的狀態(tài)圖:
對(duì)象3種狀態(tài): Transient(瞬時(shí)) Persistent(持久) Detached(托管)
臨時(shí)狀態(tài) |
new |
garbege get() load() find() iterate() etc.
持久化狀態(tài) |
save() saveOrUpdate() |
|
evict() close()* clear()* |
update() saveOrUpdate lock() |
delete() |
游離狀態(tài)
|
garbege |