在過去幾年裡Hibernate不斷發展幾乎成為Java數據庫持久性的事實標准它非常強大靈活而且具備了優異的性能在本文中我們將了解如何使用Java 注釋來簡化Hibernate代碼並使持久層的編碼過程變得更為輕松
傳統上Hibernate的配置依賴於外部 XML 文件數據庫映射被定義為一組 XML 映射文件並且在啟動時進行加載創建這些映射有很多方法可以從已有數據庫模式或Java類模型中自動創建也可以手工創建無論如何您最終將獲得大量的 Hibernate 映射文件此外還可以使用工具通過javadoc樣式的注釋生成映射文件盡管這樣會給您的構建過程增加一個步驟
在最近發布的幾個Hibernate版本中出現了一種基於 Java 注釋的更為巧妙的新方法借助新的 Hibernate Annotation 庫即可一次性地分配所有舊映射文件——一切都會按照您的想法來定義——注釋直接嵌入到您的 Java 類中並提供一種強大及靈活的方法來聲明持久性映射籍由自動代碼完成和語法突出顯示功能最近發布的Java IDE也為其提供了有力的支持
Hibernate Annotation還支持新的 EJB 持久性規范這些規范旨在提供一種標准化的 Java 持久性機制由於 Hibernate 還提供了一些擴展因此您可以十分輕松地遵從這些標准並使用 EJB 編程模型來對 Hibernate 持久層進行編碼
現在讓我們來動手使用Hibernate Annotation
安裝 Hibernate Annotation
要使用 Hibernate Annotation您至少需要具備 Hibernate 和Java 可以從 Hibernate 站點 下載 Hibernate 和 Hibernate Annotation庫除了標准的 Hibernate JAR 和依賴項之外您還需要 Hibernate Annotations jar 文件(hibernateannotationsjar)Java 持久性 API (lib/ejbpersistencejar)如果您正在使用 Maven只需要向 POM 文件添加相應的依賴項即可如下所示
<dependency>
<groupId>orghibernate</groupId>
<artifactId>hibernate</artifactId>
<version>ga</version>
</dependency>
<dependency>
<groupId>orghibernate</groupId>
<artifactId>hibernateannotations</artifactId>
<version>ga</version>
</dependency>
<dependency>
<groupId>javaxpersistence</groupId>
<artifactId>persistenceapi</artifactId>
<version></version>
</dependency>
下一步就是獲取 Hibernate 會話工廠盡管無需驚天的修改但這一工作與使用 Hibernate Annotations有所不同您需要使用 AnnotationConfiguration 類來建立會話工廠
sessionFactory = new
AnnotationConfiguration()buildSessionFactory();
盡管通常使用 <mapping> 元素來聲明持久性類您還是需要在 Hibernate 配置文件(通常是 hibernatecfgxml)中聲明持久性類
<!DOCTYPE hibernateconfiguration PUBLIC
//Hibernate/Hibernate Configuration DTD //EN
configurationdtd>
<hibernateconfiguration>
<sessionfactory>
<mapping class=comonjavamodelplanesdomainPlaneType/>
<mapping class=comonjavamodelplanesdomainModelPlane/>
</sessionfactory>
</hibernateconfiguration>
近期的許多 Java 項目都使用了輕量級的應用框架例如 Spring如果您正在使用 Spring 框架可以使用 AnnotationSessionFactoryBean 類輕松建立一個基於注釋的 Hibernate 會話工廠如下所示
<! Hibernate session factory >
<bean id=sessionFactory
class=orgspringframeworkormhibernateannotationAnnotationSessionFactoryBean>
<property name=dataSource>
<ref bean=dataSource/>
</property>
<property name=hibernateProperties>
<props>
<prop key=hibernatedialect>orghibernatedialectDerbyDialect</prop>
<prop key=hibernatehbmddlauto>create</prop>
</props>
</property>
<property name=annotatedClasses>
<list>
<value>comonjavamodelplanesdomainPlaneType</value>
<value>comonjavamodelplanesdomainModelPlane</value>
</list>
</property>
</bean>
第一個持久性類
既然已經知道了如何獲得注釋所支持的 Hibernate 會話下面讓我們來了解一下帶注釋的持久性類的情況
像在其他任何 Hibernate應用程序中一樣帶注釋的持久性類也是普通 POJO差不多可以說是您需要向 Java 持久性 API (javaxpersistence*)添加依賴項如果您正在使用任何特定於 Hibernate的擴展那很可能就是 Hibernate Annotation 程序包(orghibernateannotations*)但除此之外它們只是具備了持久性注釋的普通 POJO 下面是一個簡單的例子
@Entity
public class ModelPlane {
private Long id;
private String name;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
thisid = id;
}
public String getName() {
return name;
}
public void setName(String name) {
thisname = name;
}
}
正像我們所提到的這非常簡單@Entity 注釋聲明該類為持久類@Id 注釋可以表明哪種屬性是該類中的獨特標識符事實上您既可以保持字段(注釋成員變量)也可以保持屬性(注釋getter方法)的持久性後文中將使用基於屬性的注釋基於注釋的持久性的優點之一在於大量使用了默認值(最大的優點就是 慣例優先原則(convention over configuration))例如您無需說明每個屬性的持久性——任何屬性都被假定為持久的除非您使用 @Transient 注釋來說明其他情況這簡化了代碼相對使用老的 XML 映射文件而言也大幅地減少了輸入工作量
生成主鍵
Hibernate 能夠出色地自動生成主鍵Hibernate/EBJ 注釋也可以為主鍵的自動生成提供豐富的支持允許實現各種策略下面的示例說明了一種常用的方法其中 Hibernate 將會根據底層數據庫來確定一種恰當的鍵生成策略
@Id
@GeneratedValue(strategy=GenerationTypeAUTO)
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) {
thisid = id;
}
@Column(name=PLANE_NAME)
public String getName() {
return name;
}
public void setName(String name) {
thisname = name;
}
}
該內容將映射到下表中
CREATE TABLE T_MODEL_PLANE
(
PLANE_ID long
PLANE_NAME varchar
)
也可以使用其他圖和列的屬性來定制映射這使您可以指定諸如列長度非空約束等詳細內容Hibernate支持大量針對這些注釋的屬性下例中就包含了幾種屬性
@Column(name=PLANE_ID length= nullable=true)
public String getName() {
return name;
}
映射關系
Java 持久性映射過程中最重要和最復雜的一環就是確定如何映射表間的關系像其他產品一樣 Hibernate 在該領域中提供了高度的靈活性但卻是以復雜度的增加為代價我們將通過研究幾個常見案例來了解如何使用注釋來處理這一問題
其中一種最常用的關系就是多對一的關系假定在以上示例中每個 ModelPlane 通過多對一的關系(也就是說每個飛機模型只與一種飛機類型建立聯系盡管指定的飛機類型可以與七種飛機模型建立聯系)來與 PlaneType 建立聯系可如下進行映射
@ManyToOne( cascade = {CascadeTypePERSIST CascadeTypeMERGE} )
public PlaneType getPlaneType() {
return planeType;
}
CascadeType 值表明 Hibernate 應如何處理級聯操作
另一種常用的關系與上述關系相反一對多再對一關系也稱為集合在老式的 Hibernate 版本中進行映射或使用注釋時集合令人頭疼這裡我們將簡要加以探討以使您了解如何處理集合例如在以上示例中每個 PlaneType 對象都可能會包含一個 ModelPlanes 集合可映射如下
@OneToMany(mappedBy=planeType
cascade=CascadeTypeALL
fetch=FetchTypeEAGER)
@OrderBy(name)
public List<ModelPlane> getModelPlanes() {
return modelPlanes;
}
命名查詢
Hibernate 最優秀的功能之一就在於它能夠在您的映射文件中聲明命名查詢隨後即可通過代碼中的名稱調用此類查詢這使您可以專注於查詢而避免了 SQL 或者 HQL 代碼分散於整個應用程序中的情況
也可以使用注釋來實現命名查詢可以使用 @NamedQueries 和 @NamedQuery 注釋如下所示
@NamedQueries(
{
@NamedQuery(
name=planeTypefindById
query=select p from PlaneType p left join fetch pmodelPlanes where id=:id
)
@NamedQuery(
name=planeTypefindAll
query=select p from PlaneType p
)
@NamedQuery(
name=planeTypedelete
query=delete from PlaneType where id=:id
)
}
)
一旦完成了定義您就可以像調用其他任何其他命名查詢一樣來調用它們
結束語
Hibernate 注釋提供了強大而精致的 API簡化了 Java 數據庫中的持久性代碼本文中只進行了簡單的討論您可以選擇遵從標准並使用 Java 持久性 API也可以利用特定於 Hibernate的擴展這些功能以損失可移植性為代價提供了更為強大的功能和更高的靈活性無論如何通過消除對 XML 映射文件的需求Hibernate 注釋將簡化應用程序的維護同時也可以使您對EJB 有初步認識來試試吧!
資源
Hibernate 站點
Spring 站點
作者簡介
John Ferguson Smart 從
年起涉足IT行業
從
年起開始參與J
EE開發
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28299.html