作者:Willpower
來(lái)源:Rifoo Technology( http://www.rifoo.com )
時(shí)間:2006-05
備注:轉(zhuǎn)載請(qǐng)保留以上聲明
**/
今天開始Hibernate3之旅,在Hibernate2的基礎(chǔ)上改進(jìn)了不少,讓我們一起借助這本書來(lái)學(xué)習(xí)吧。
本書分兩個(gè)部分,第一部分是Hibernate入門知識(shí)(第1到4章),第二部分是Hibernate高級(jí)知識(shí)(第5到14章)。
我們今天來(lái)看看第一章的內(nèi)容:Hibernate 3的介紹。
大多數(shù)重大的開發(fā)項(xiàng)目都會(huì)涉及到關(guān)系數(shù)據(jù)庫(kù)的概念。許多商業(yè)應(yīng)用的核心就是對(duì)規(guī)則有序的信息進(jìn)行大規(guī)模的存儲(chǔ),比如目錄,客戶列表,合同資料等。
隨著互聯(lián)網(wǎng)的繁榮,對(duì)數(shù)據(jù)庫(kù)的要求越來(lái)越高。在線書店的那些客戶們可能自己都不知道,自己每一次的查詢操作或者點(diǎn)擊某個(gè)按鈕都會(huì)去操作數(shù)據(jù)庫(kù)。
隨著應(yīng)用程序的需求不段提高,后來(lái)出現(xiàn)了標(biāo)準(zhǔn)的EJB規(guī)范,EJB規(guī)范提供了容器和Bean管理的CMP。但是,這個(gè)復(fù)雜性很高,而性能卻并沒(méi)有想像中的高。后來(lái),Hibernate的出現(xiàn)給數(shù)據(jù)的持久化帶來(lái)了很大的轟動(dòng)。針對(duì)一些數(shù)據(jù)庫(kù)持久化解決方案,有用EJB的,有用傳統(tǒng)JDBC的,有用Hibernate的。但Hibernate在易用性上顯示了突出的優(yōu)勢(shì)。
這一章我們會(huì)提供給大家一個(gè)“Hello world”數(shù)據(jù)庫(kù)范例。該范例能夠通過(guò)一個(gè)簡(jiǎn)單的關(guān)鍵字來(lái)查找并顯示數(shù)據(jù)庫(kù)中被保存的一個(gè)message信息。下面我們會(huì)提供原始JDBC寫法和Hibernate寫法:
Listing 1-1. 這個(gè)Main方法會(huì)調(diào)用我們Hibernate或JDBC的持久化操作
CODE:
public static void main(String[] args) {
? if (args.length != 1) {
? ? System.err.println("Nope, enter one message number");
? } else {
? try {
? ? int messageId = Integer.parseInt(args[0]);
? ? //這一句是調(diào)用的方法
? ? [b]Motd motd = getMotd(messageId);[/b]
? ? if (motd != null) {
? ? ? ? System.out.println(motd.getMessage());
? ? } else {
? ? ? ? System.out.println("No such message");
? ? }
? } catch (NumberFormatException e) {
? ? System.err.println("You must enter an integer - " + args[0]
? ? ? ? + " won't do.");
? } catch (MotdException e) {
? ? System.err.println("Couldn't get the message: " + e);
? ? }
? }
}
在理想的世界中,我們將很容易的獲取任何JAVA對(duì)象并將它持久化到數(shù)據(jù)庫(kù)。不需要編寫額外的特殊代碼。也能夠保證有良好的性能。對(duì)象關(guān)系映射(Object Relational Mapping)技術(shù)能持久化傳統(tǒng)的JAVA對(duì)象,而這里的POJO(Plain Old Java Objects)也是一種可重用的JAVA對(duì)象,POJO可以是任意的JAVA對(duì)象,而不需要Entity Bean那樣的命名約束。Hibernate能夠幫助我們很輕松地去持久化POJO。
下面我們編寫POJO部分:
Listing 1-2. 本范例中使用到的POJO
CODE:
public class Motd {
? protected Motd() {
? }
? public Motd(int messageId, String message) {
? ? this.messageId = messageId;
? ? this.message = message;
? }
? public int getId() {
? ? return id;
? }
? public void setId(int id) {
? ? this.id = id;
? }
? public String getMessage() {
? ? return message;
? }
? public void setMessage(String message) {
? ? this.message = message;
? }
? private int messageId;
? private String message;
}
下面是從數(shù)據(jù)庫(kù)中檢索Motd對(duì)象的傳統(tǒng)JDBC的寫法,代碼如下:
Listing 1-3. 檢索POJO
CODE:
public static Motd getMotd(int messageId) throws MotdException {
? Connection c = null;
? PreparedStatement p = null;
? Motd message = null;
? try {
? Class.forName("org.postgresql.Driver");
? c = DriverManager.getConnection(
? ? "jdbc:postgresql://127.0.0.1/hibernate",
? ? "hibernate",
? ? "hibernate");
? p = c.prepareStatement(
? "select message from motd where id = ?");
? p.setInt(1, messageId);
? ResultSet rs = p.executeQuery();
? ? if (rs.next()) {
? ? ? ? String text = rs.getString(1);
? ? ? ? message = new Motd(messageId, text);
? ? ? ? if (rs.next()) {
? ? ? ? ? log.warning(
? ? ? ? ? "Multiple messages retrieved for message ID: "
? ? ? ? ? + messageId);
? ? ? ? ? }
? ? ? ? }
? ? } catch (Exception e) {
? ? log.log(Level.SEVERE, "Could not acquire message", e);
? ? throw new MotdException(
? ? "Failed to retrieve message from the database.", e);
? } finally {
? ? if (p != null) {
? ? ? ? try {
? ? ? ? ? p.close();
? ? ? ? } catch (SQLException e) {
? ? ? ? ? log.log(Level.WARNING,
? ? ? ? ? "Could not close ostensibly open statement.", e);
? ? ? ? }
? ? }
? ? if (c != null) {
? ? ? ? try {
? ? ? ? ? c.close();
? ? ? ? } catch (SQLException e) {
? ? ? ? log.log(Level.WARNING,
? ? ? ? "Could not close ostensibly open connection.", e);
? ? ? ? }
? ? }
? } ?
return message;
}
大家都看到了,這段代碼包括數(shù)據(jù)庫(kù)連接建立,釋放資源等。對(duì)于每個(gè)查詢的方法,都有這樣的代碼,其實(shí)這個(gè)顯得很冗余。當(dāng)然了,我們也可以對(duì)它進(jìn)行重構(gòu),將這部分代碼提取出來(lái),提供一些樣本方法。