?? hibernate2 參考文檔之一.txt
字號:
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/quickstart</property>
<property name="show_sql">false</property>
<property name="dialect">net.sf.hibernate.dialect.PostgreSQLDialect</property>
<!-- Mapping files -->
<mapping resource="Cat.hbm.xml"/>
</session-factory>
</hibernate-configuration>
我們關(guān)閉了SQL命令的log,告訴Hibernate使用哪種SQL數(shù)據(jù)庫方言(dialet),還有如何得到JDBC連接(通過聲明數(shù)據(jù)源池綁定的JNDI地址)。方言是必需的,因?yàn)椴煌臄?shù)據(jù)庫都和SQL "標(biāo)準(zhǔn)"有一些出入。Hibernate會替你照管這些差異之處,發(fā)行包包含了所有主流的商業(yè)和開放源代碼數(shù)據(jù)庫的方言。
SessionFactory是Hibernate的概念,對應(yīng)一個數(shù)據(jù)存儲源,如果有多個數(shù)據(jù)庫,可以創(chuàng)建多個XML配置文件,也在你的程序中創(chuàng)建多個Configuration和SessionFactory對象。
在hibernate.cfg.xml中的最后一個元素聲明了Cat.hbm.xml是一個Hibernate XML映射文件,對應(yīng)持久化類Cat。這個文件包含了把POJO類映射到數(shù)據(jù)庫表(或多個數(shù)據(jù)庫表)的元數(shù)據(jù)。我們稍后就回來看這個文件。讓我們先編寫這個POJO類,再在聲明它的映射元數(shù)據(jù)。
1.2. 第一個可持久化類
s Hibernate讓普通的Java對象(Plain Old Java Objects ,就是POJOs,有時候也稱作Plain Ordinary Java Objects)變成持久化類。一個POJO很像JavaBean,屬性通過getter和setter方法訪問,對外隱藏了內(nèi)部實(shí)現(xiàn)的細(xì)節(jié)。
package net.sf.hibernate.examples.quickstart;
public class Cat {
private String id;
private String name;
private char sex;
private float weight;
public Cat() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
}
Hibernate對屬性使用的類型不加限制。所有的Java JDK類型和原始類型(比如String,char和float)都可以被映射,也包括Java 集合框架(Java collections framework)中的類。你可以把它們映射成為值,值集合,或者與其他實(shí)體相關(guān)聯(lián)。id是一個特殊的屬性,代表了這個類的數(shù)據(jù)庫標(biāo)識符(主鍵),它對于類似于Cat這樣的實(shí)體是必需的。
持久化類不需要實(shí)現(xiàn)什么特別的接口,也不需要從一個特別的持久化根類繼承下來。Hibernate也不需要使用任何編譯期處理,比如字節(jié)碼增強(qiáng)操作,它獨(dú)立的使用Java反射機(jī)制和運(yùn)行時類增強(qiáng)(通過CGLIB)。所以,在Hibernate中,POJO的類不需要任何前提條件,我們就可以把它映射成為數(shù)據(jù)庫表。
1.3. 映射cat
Cat.hbm.xml映射文件包含了對象/關(guān)系映射所需的元數(shù)據(jù)。
元數(shù)據(jù)包含了持久化類的聲明和把它與其屬性映射到數(shù)據(jù)庫表的信息(屬性作為值或者是指向其他實(shí)體的關(guān)聯(lián))。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="net.sf.hibernate.examples.quickstart.Cat" table="CAT">
<!-- A 32 hex character is our surrogate key. It's automatically
generated by Hibernate with the UUID pattern. -->
<id name="id" type="string" unsaved-value="null" >
<column name="CAT_ID" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex"/>
</id>
<!-- A cat has to have a name, but it shouldn' be too long. -->
<property name="name">
<column name="NAME" sql-type="varchar(16)" not-null="true"/>
</property>
<property name="sex"/>
<property name="weight"/>
</class>
</hibernate-mapping>
每個持久化類都需要一個標(biāo)識屬性(實(shí)際上,只是哪些代表一手對象的類,而不是代表值對象的類,后者會被映射稱為一手對象中的一個組件)。這個屬性用來區(qū)分持久化對象:如果catA.getId().equals(catB.getId())結(jié)果是true的話,兩只貓就是相同的。這個概念稱為數(shù)據(jù)庫標(biāo)識。Hiernate附帶了幾種不同的標(biāo)識符生成器,用于不同的場合(包括數(shù)據(jù)庫本地的順序(sequence)生成器和hi/lo高低位標(biāo)識模式)。我們在這里使用UUID生成器,并指定CAT表的CAT_ID字段(作為表的主鍵)存放生成的標(biāo)識值。
Cat的其他屬性都映射到同一個表。對name屬性來說,我們把它顯式地聲明映射到一個數(shù)據(jù)庫字段。如果數(shù)據(jù)庫schema是由映射聲明使用Hibernate的SchemaExport工具自動生成的(作為SQL DDL指令),這特別有用。所有其它的屬性都用Hibernate的默認(rèn)值映射,大多數(shù)情況你都會這樣做。數(shù)據(jù)庫中的CAT表看起來是這樣的:
Column | Type | Modifiers
--------+-----------------------+-----------
cat_id | character(32) | not null
name | character varying(16) | not null
sex | character(1) |
weight | real |
Indexes: cat_pkey primary key btree (cat_id)
你現(xiàn)在可以在你的數(shù)據(jù)庫中首先創(chuàng)建這個表了,如果你需要使用SchemaExport工具把這個步驟自動化,請參閱Chapter 19, 工具箱指南。這個工具能夠創(chuàng)建完整的SQL DDL,包括表定義,自定義的字段類型約束,惟一約束和索引。
1.4. 與貓同樂
我們現(xiàn)在可以開始Hibernate的Session了。我們用它來從數(shù)據(jù)庫中存取Cat。首先,我們要從SessionFactory中獲取一個Session(Hibernate的工作單元)。
SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory();
SessionFactory負(fù)責(zé)一個數(shù)據(jù)庫,也只對應(yīng)一個XML配置文件(hibernate.cfg.xml)。
這篇教程的關(guān)注點(diǎn)在于配置Tomcat的JDBC連接,綁定到JNDI上,以及Hibernate的基礎(chǔ)配置。你可以用喜歡的任何方式編寫一個Servlet,包含下面的代碼,只要確保SessionFactory只創(chuàng)建一次。也就是說你不能把它作為你的Serlvet 的實(shí)例變量。一個好辦法是用在輔助類中用一個靜態(tài)的SessionFactory,例如這樣:
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (HibernateException ex) {
throw new RuntimeException("Exception building SessionFactory: " + ex.getMessage(), ex);
}
}
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
這個類不但在它的靜態(tài)屬性中使用了SessionFactory,還使用了ThreadLocal來為當(dāng)前工作線程保存Session。
Session不是線程安全的,代表與數(shù)據(jù)庫之間的一次操作。Session通過SessionFactory打開,在所有的工作完成后,需要關(guān)閉:
Session session = HibernateUtil.currentSession();
Transaction tx= session.beginTransaction();
Cat princess = new Cat();
princess.setName("Princess");
princess.setSex('F');
princess.setWeight(7.4f);
session.save(princess);
tx.commit();
HibernateUtil.closeSession();
在Session中,每個數(shù)據(jù)庫操作都是在一個事務(wù)(transaction)中進(jìn)行的,這樣就可以隔離開不同的操作(甚至包括只讀操作)。我們使用Hibernate的Transaction API來從底層的事務(wù)策略中(本例中是JDBC事務(wù))脫身。這樣,如果需要把我們的程序部署到一個由容器管理事務(wù)的環(huán)境中去(使用JTA),我們就不需要更改源代碼。請注意,我們上面的例子沒有處理任何異常。
也請注意,你可以隨心所欲的多次調(diào)用HibernateUtil.currentSession();,你每次都會得到同一個當(dāng)前線程的Session。你必須確保Session在你的數(shù)據(jù)庫事務(wù)完成后關(guān)閉,不管是在你的Servlet代碼中,或者在ServletFilter中,HTTP結(jié)果返回之前。
Hibernate有不同的方法來從數(shù)據(jù)庫中取回對象。最靈活的方式是使用Hibernate查詢語言(HQL),這是一種容易學(xué)習(xí)的語言,是對SQL的面向?qū)ο蟮膹?qiáng)大擴(kuò)展。
Transaction tx= session.beginTransaction();
Query query = session.createQuery("select cat from Cat as cat where cat.sex = :sex");
query.setCharacter("sex", 'F');
for (Iterator it = query.iterate(); it.hasNext();) {
Cat cat = (Cat) it.next();
out.println("Female Cat: " + cat.getName() );
}
tx.commit();
Hibernate也提供一種面向?qū)ο蟮陌礂l件查詢API,可以執(zhí)行公式化的類型安全的查詢。當(dāng)然,Hibernate在所有與數(shù)據(jù)庫的交互中都使用PrepatedStatement和參數(shù)綁定。
1.5. 結(jié)語
在這個短小的教程中,我們只描繪了Hibernate的基本面目。請注意我們沒有在例子中包含Servlet相關(guān)代碼。你必須自行編寫Servlet,然后把你認(rèn)為合適的Hibernate代碼插入。
請記住Hibernate作為數(shù)據(jù)庫訪問層,是與你的程序緊密相關(guān)的。一般,所有其他層次都依賴持久機(jī)制。請確信你理解了這種設(shè)計的含義。
--------------------------------------------------------------------------------
Prev Up Next
前言 Home Chapter 2. 體系結(jié)構(gòu)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -