上面的這個(gè)圖是Hiberante應用程序的結構,
對上圖中各項的說(shuō)明如下:(1)Application:應用 (2)Persistent Object:持久化對象(3)hibernate.properties:Hibernate屬性文件/Hibernate配置文件 (4)XML Mapping:Hibernate映射文件 (5)Database:數據庫
由上圖可以看出,Hibernate是通過(guò)一系列的配置文件和數據庫來(lái)實(shí)現持久化對象的持久化操作的。
為了使用Hibernate,需要創(chuàng )建與數據庫中的表對應的持久化對象,然后再通過(guò)影射文件將持久化對象中的屬性與數據庫表中的字段對應起來(lái)。這樣才能通過(guò)持久化對象完成對數據庫表中的數據的增加、修改、查詢(xún)和刪除操作。
Hibernate主要包括三個(gè)組件:
(1)連接管理組件:它提供了高效的數據庫連接管理。數據庫連接是和數據庫進(jìn)行交互的唯一渠道,建立和關(guān)閉一個(gè)連接需要耗費大量的資源。所以現在的應用程序都采用連接池的方法來(lái)管理與數據庫的連接,避免頻繁的建立和關(guān)閉數據庫連接
(2)事務(wù)管理組件:通過(guò)事務(wù),一次可以執行多個(gè)SQL語(yǔ)句,而且能夠保證這些語(yǔ)句執行成功或者都不成功
(3)對象/關(guān)系映射組建:對象/映射技術(shù)可以實(shí)現從對象模型到數據庫中關(guān)系模型的映射工作。通過(guò)這一技術(shù),Hibernate實(shí)現了對象的持久化操作。
Hinernate的體系結構(運行時(shí))
由于Hibernate非常靈活,而且提供了多種運行
時(shí)的結構組成方案,這里介紹的時(shí)一個(gè)“最全面”的體系結構,它最大程度的完成了對持久層功能的封裝,也就使得在開(kāi)發(fā)中要完成的工作量最少,是在
開(kāi)發(fā)中最經(jīng)常使用的一種方式。這種方式把JDBC/JTA都交由Hibernate去完成,而不需要對這一部分進(jìn)行任何處。
SessionFactory:它保存了對當前數據庫配置的所有映射關(guān)系,它是將某個(gè)數據庫的映射關(guān)系經(jīng)過(guò)編譯之后全部保存在內存中的。 它還是生成Session的工廠(chǎng),它在進(jìn)行實(shí)例化的過(guò)程中將會(huì )用到ConnectionProvider。
一個(gè)SessionFactory對應一個(gè)數據庫連接,當數據庫連接改變時(shí)需要修改SessionFactorySesion:是進(jìn)行持久化操作的基礎,所有的持久化操作都是在Session的基礎上進(jìn)行的。它相當與JDBC中的Connection。它是Hibernate的持久化管理器的核心,提供了一系列的持久化操作方法。另外,它還持有一個(gè)針對持久化對象的一級緩存,在遍歷持久化對象或者根據持久化標識查找對象的時(shí)候會(huì )用到。
Transation:功能上和數據庫中的事務(wù)完全一樣,通過(guò)它實(shí)現對數據庫中事務(wù)的控制。Transation對象是Session對象產(chǎn)生的,所以他的生命周期比Session短。一個(gè)Session的生命周期中可以有多個(gè)Transaction對象。
ConnectonProvider:主要作用是生成與數據庫建立了連接的JDBC對象,同時(shí)他還作為數據庫連接的緩沖池。通過(guò)ConnectionProvider實(shí)現了應用程序和底層的DataSource和DriverManager的隔離。
TransactionFactory:是生成Transaction對象的工廠(chǎng),通過(guò)TransactionFactory實(shí)現了事務(wù)的封裝,使其具體的實(shí)現方法與應用程序無(wú)關(guān)。
Hibernate對象的生命周期
一共有三種生命周期:
(1)瞬態(tài):表示該實(shí)體對象在內存中是自由存在的,也就是說(shuō)與數據庫中的數據沒(méi)有任何的關(guān)聯(lián)。即,該實(shí)體從未與任何持久化上下文聯(lián)系過(guò),沒(méi)有持久化標識(相當與主鍵)。瞬態(tài)實(shí)體的特征有:
與數據庫中的記錄沒(méi)有任何關(guān)聯(lián),也就是沒(méi)有與其相關(guān)聯(lián)的數據庫記錄
與Session沒(méi)有任何關(guān)系,也就是沒(méi)有通過(guò)Session對象的實(shí)例對其進(jìn)行任何持久化的操作。
(2)持久態(tài):指該實(shí)體對象處于Hibernate框架所管理的狀態(tài),也就是說(shuō)這個(gè)實(shí)體對象是與Session對象的實(shí)例相關(guān)的。
處于持久態(tài)的實(shí)體對象的最大特征是對其所作的任何變更操作都將被Hibernate持久化到數據庫中。處于持久態(tài)的對象具有的特征為: 每個(gè)持久態(tài)對象都于一個(gè)Session對象關(guān)聯(lián)
處于持久態(tài)的對象是于數據庫中的記錄相關(guān)聯(lián)的
Hibernate會(huì )根據持久態(tài)對象的屬性的變化而改變數據庫中的相應記錄
(3)游離態(tài):處于持久態(tài)的實(shí)體對象,當他不再與Session對象關(guān)聯(lián)時(shí),這個(gè)對象就變成了游離態(tài)。。游離態(tài)對象的特征有:
游離態(tài)對象一定是由持久態(tài)對象轉換而來(lái)
游離態(tài)實(shí)體不再于Session關(guān)聯(lián)
游離態(tài)實(shí)體對象與數據庫中的數據沒(méi)有直接聯(lián)系,主要表現在對其進(jìn)行的修改不再影響到數據庫中的數據
游離態(tài)實(shí)體對象在數據庫中有相應的數據記錄(如果該記錄沒(méi)有被刪除)
判斷一個(gè)實(shí)體對象是否處于瞬態(tài):
該實(shí)體對象的<id>屬性(如果存在)的值為空
如果在映射文件中為<id>設置了unsaved-value屬性,并且實(shí)體對象的id屬性的值與unsaved-value屬性的值相同
如果這個(gè)實(shí)體對象配置version屬性,并且version屬性的值為空
在映射文件中為version屬性設置了unsaved-value屬性,并且version屬性的值與unsaved-value屬性的值相同。
如果設置了interceptor,并且interceptor的isUnsaved()方法的返回值為true
滿(mǎn)足上述條件的實(shí)體對象就處于瞬態(tài),否則為游離態(tài)(前提是不處于持久態(tài))
下面通過(guò)一段代碼來(lái)說(shuō)明狀態(tài)問(wèn)題:
public class LifeCycle
{
public static final SessionFactory sessionFactory;
static
{
sessionFactory = new Configuration().configure().buildSessionFactory();
}
public static void main(String[] args)
{
LifeCycle.lifecycle();
}
public static void lifecycle()
{
// 創(chuàng )建游離態(tài)實(shí)體對象User
User user = new User();
user.setName( "abc" + String.valueOf( Math.random() ) );
// 為了避免兩次運行的用戶(hù)名重復,所以增加了隨機數
user.setPassword( "def" );
// user仍然處于游離態(tài)
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
// 此時(shí)user對象仍然是Transient狀態(tài)
session.save( user );
// 此時(shí),user對象已經(jīng)被納入了Hibernate的實(shí)體管理容器中,并轉變?yōu)镻ersistent狀態(tài)
System.out.println( "User 1:" + user );
// 此時(shí)的id已經(jīng)有值了。
get( user.getId() );
// 但并未真正的執行數據庫的操作,所以無(wú)法得到對象的值
tx.commit();
// 事務(wù)被提交后,將向數據庫的用戶(hù)表中插入一條記錄
System.out.println( "Transaction 1 commit!" );
get( user.getId() );
// 這時(shí)可以由數據庫中得到剛才插入的user對象了。
Transaction tx2 = session.beginTransaction();
user.setPassword( "mmmmmmmmmmmmm" );
tx2.commit();
// 雖然這個(gè)事務(wù)中并沒(méi)有調用Session的save()方法來(lái)保存user對象
// 但由于user對象處于Persistent狀態(tài),所以對user對象所做的任何修改都將被持久化到數據庫中
// 那么數據庫中的用戶(hù)密碼也應該變?yōu)榱薲ef。
System.out.println( "Transaction 2 commit!" );
session.close();
get( user.getId() );
// 此時(shí)密碼已經(jīng)變?yōu)樾碌闹盗?br> }
public static User get( String id )
{
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = (User)session.get( User.class, id );
// Hibernate在返回User對象之間會(huì )將其納入到Hibernate的實(shí)體管理容器中
// 所以,這時(shí)的user對象是Persistent狀態(tài)的
display( user );
tx.commit();
session.close();
return user;
}
public static void display( Object obj )
{
System.out.println( obj );
}
}
提示1:Hibernate支持四種數據庫連接池的組件 (2)DBCP:它是Apache軟件基金組織的一個(gè)開(kāi)源項目。由于在Hibernte3中不再提供DBCConnectionProvider類(lèi)來(lái)直接使用DBCP建立數據庫的連接池,在這里提供兩種方法解決這個(gè)問(wèn)題。一種是仿照Hibernate2中的DBCPConnectionProvider類(lèi)自己實(shí)現一個(gè)使用DBCP并實(shí)現了ConnetcitonProvider接口的連接池類(lèi)。另一種是讓?xiě)梅?wù)器通過(guò)JNDI的方式來(lái)提供數據庫的連接,Hibernate通過(guò)JNDI得到數據庫的連接。DBCP的詳細信息見(jiàn):
http://jakarta.apache.org/commons/dbcp/。關(guān)于自己實(shí)現ConnectionProvider接口的方法見(jiàn)
http://wiki.apache.org/jakarta-commons/DBCP/Hibernate