Hibernate 3註釋簡介
在過去幾年裡,Hibernate不斷髮展,幾乎成為Java資料庫永續性的事實標準。它非常強大、靈活,而且具備了優異的效能。在本文中,我們將瞭解如何使用Java 5 註釋來簡化Hibernate程式碼,並使持久層的編碼過程變得更為輕鬆。
傳統上,Hibernate的配置依賴於外部 XML 檔案:資料庫對映被定義為一組 XML 對映檔案,並且在啟動時進行載入。建立這些對映有很多方法,可以從已有資料庫模式或Java類模型中自動建立,也可以手工建立。無論如何,您最終將獲得大量的 Hibernate 對映檔案。此外,還可以使用工具,通過javadoc樣式的註釋生成對映檔案,儘管這樣會給您的構建過程增加一個步驟。
在最近釋出的幾個Hibernate版本中,出現了一種基於 Java 5 註釋的更為巧妙的新方法。藉助新的 Hibernate Annotation 庫,即可一次性地分配所有舊對映檔案——一切都會按照您的想法來定義——註釋直接嵌入到您的 Java 類中,並提供一種強大及靈活的方法來宣告永續性對映。籍由自動程式碼完成和語法突出顯示功能,最近釋出的Java IDE也為其提供了有力的支援。
Hibernate Annotation還支援新的 EJB 3 永續性規範。這些規範旨在提供一種標準化的 Java 永續性機制。由於 Hibernate 3 還提供了一些擴充套件,因此您可以十分輕鬆地遵從這些標準,並使用 EJB 3 程式設計模型來對 Hibernate 持久層進行編碼。
現在,讓我們來動手使用Hibernate Annotation。
安裝 Hibernate Annotation
要使用 Hibernate Annotation,您至少需要具備 Hibernate 3.2和Java 5。可以從 Hibernate 站點 下載 Hibernate 3.2 和 Hibernate Annotation庫。除了標準的 Hibernate JAR 和依賴項之外,您還需要 Hibernate Annotations .jar 檔案(hibernate-annotations.jar)、Java 永續性 API (lib/ejb3-persistence.jar
... <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.1.ga</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-annotations</artifactId> <version>3.2.0.ga</version> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency> ...
下一步就是獲取 Hibernate 會話工廠。儘管無需驚天的修改,但這一工作與使用 Hibernate Annotations有所不同。您需要使用 AnnotationConfiguration 類來建立會話工廠:
sessionFactory = new
AnnotationConfiguration().buildSessionFactory();
儘管通常使用 <mapping> 元素來宣告永續性類,您還是需要在 Hibernate 配置檔案(通常是 hibernate.cfg.xml)中宣告永續性類:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <mapping class="com.onjava.modelplanes.domain.PlaneType"/> <mapping class="com.onjava.modelplanes.domain.ModelPlane"/> </session-factory> </hibernate-configuration>
近期的許多 Java 專案都使用了輕量級的應用框架,例如 Spring。如果您正在使用 Spring 框架,可以使用 AnnotationSessionFactoryBean 類輕鬆建立一個基於註釋的 Hibernate 會話工廠,如下所示:
<!-- Hibernate session factory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> ... </props> </property> <property name="annotatedClasses"> <list> <value>com.onjava.modelplanes.domain.PlaneType</value> <value>com.onjava.modelplanes.domain.ModelPlane</value> ... </list> </property> </bean>
第一個永續性類
既然已經知道了如何獲得註釋所支援的 Hibernate 會話,下面讓我們來了解一下帶註釋的永續性類的情況:
像在其他任何 Hibernate應用程式中一樣,帶註釋的永續性類也是普通 POJO。差不多可以說是。您需要向 Java 永續性 API (javax.persistence.*)新增依賴項,如果您正在使用任何特定於 Hibernate的擴充套件,那很可能就是 Hibernate Annotation 程式包(org.hibernate.annotations.*),但除此之外,它們只是具備了永續性註釋的普通 POJO 。下面是一個簡單的例子:
@Entity public class ModelPlane { private Long id; private String name; @Id public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
正像我們所提到的,這非常簡單。@Entity 註釋宣告該類為持久類。@Id 註釋可以表明哪種屬性是該類中的獨特識別符號。事實上,您既可以保持欄位(註釋成員變數),也可以保持屬性(註釋getter方法)的永續性。後文中將使用基於屬性的註釋。基於註釋的永續性的優點之一在於大量使用了預設值(最大的優點就是 “慣例優先原則(convention over configuration)”)。例如,您無需說明每個屬性的永續性——任何屬性都被假定為持久的,除非您使用 @Transient 註釋來說明其他情況。這簡化了程式碼,相對使用老的 XML 對映檔案而言也大幅地減少了輸入工作量。
生成主鍵
Hibernate 能夠出色地自動生成主鍵。Hibernate/EBJ 3 註釋也可以為主鍵的自動生成提供豐富的支援,允許實現各種策略。下面的示例說明了一種常用的方法,其中 Hibernate 將會根據底層資料庫來確定一種恰當的鍵生成策略:
@Id @GeneratedValue(strategy=GenerationType.AUTO) public Long getId() { return id; }
定製表和欄位對映
預設情況下,Hibernate 會將持久類以匹配的名稱對映到表和欄位中。例如,前一個類可以與對映到以如下程式碼建立的表中:
CREATE TABLE MODELPLANE ( ID long, NAME varchar )
如果您是自己生成並維護資料庫,那麼這種方法很有效,通過省略程式碼可以大大簡化程式碼維護。然而,這並不能滿足所有人的需求。有些應用程式需要訪問外部資料庫,而另一些可能需要遵從公司的資料庫命名慣例。如果有必要,您可以使用 @Table 和 @Column 註釋來定製您自己的永續性對映,如下所示:
@Entity @Table(name="T_MODEL_PLANE") public class ModelPlane { private Long id; private String name; @Id @Column(name="PLANE_ID") public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name="PLANE_NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } }
該內容將對映到下表中:
CREATE TABLE T_MODEL_PLANE ( PLANE_ID long, PLANE_NAME varchar )
也可以使用其他圖和列的屬性來定製對映。這使您可以指定諸如列長度、非空約束等詳細內容。Hibernate支援大量針對這些註釋的屬性。下例中就包含了幾種屬性:
... @Column(name="PLANE_ID", length=80, nullable=true) public String getName() { return name; } ...
對映關係
Java 永續性對映過程中最重要和最複雜的一環就是確定如何對映表間的關係。像其他產品一樣, Hibernate 在該領域中提供了高度的靈活性,但卻是以複雜度的增加為代價。我們將通過研究幾個常見案例來了解如何使用註釋來處理這一問題。
其中一種最常用的關係就是多對一的關係。假定在以上示例中每個 ModelPlane 通過多對一的關係(也就是說,每個飛機模型只與一種飛機型別建立聯絡,儘管指定的飛機型別可以與七種飛機模型建立聯絡)來與 PlaneType 建立聯絡。可如下進行對映:
@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) public PlaneType getPlaneType() { return planeType; }
CascadeType 值表明 Hibernate 應如何處理級聯操作。
另一種常用的關係與上述關係相反:一對多再對一關係,也稱為集合。在老式的 Hibernate 版本中進行對映或使用註釋時,集合令人頭疼,這裡我們將簡要加以探討,以使您瞭解如何處理集合,例如,在以上示例中每個 PlaneType 物件都可能會包含一個 ModelPlanes 集合。可對映如下:
@OneToMany(mappedBy="planeType", cascade=CascadeType.ALL, fetch=FetchType.EAGER) @OrderBy("name") public List<ModelPlane> getModelPlanes() { return modelPlanes; }
命名查詢
Hibernate 最優秀的功能之一就在於它能夠在您的對映檔案中宣告命名查詢。隨後即可通過程式碼中的名稱呼叫此類查詢,這使您可以專注於查詢,而避免了 SQL 或者 HQL 程式碼分散於整個應用程式中的情況。
也可以使用註釋來實現命名查詢,可以使用 @NamedQueries 和 @NamedQuery 註釋,如下所示:
@NamedQueries( { @NamedQuery( name="planeType.findById", query="select p from PlaneType p left join fetch p.modelPlanes where id=:id" ), @NamedQuery( name="planeType.findAll", query="select p from PlaneType p" ), @NamedQuery( name="planeType.delete", query="delete from PlaneType where id=:id" ) } )
一旦完成了定義,您就可以像呼叫其他任何其他命名查詢一樣來呼叫它們。
結束語
Hibernate 3 註釋提供了強大而精緻的 API,簡化了 Java 資料庫中的永續性程式碼,本文中只進行了簡單的討論。您可以選擇遵從標準並使用 Java 永續性 API,也可以利用特定於 Hibernate的擴充套件,這些功能以損失可移植性為代價提供了更為強大的功能和更高的靈活性。無論如何,通過消除對 XML 對映檔案的需求,Hibernate 註釋將簡化應用程式的維護,同時也可以使您對EJB 3 有初步認識。來試試吧!