JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Object Relational Mapping » Hibernate  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
己加入精華區
by koji at 2006-07-26 14:37
本主題所含的標籤
無標籤
作者 [教學] Hibernate入門 [精華]
qrtt1





發文: 1746
積分: 31
於 2006-04-26 05:55 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
前言

雖然,看過了許多前輩長輩的分享。但是總覺得自己也想寫寫這一篇文章。自己寫的總是有不同的感受,也幫助自己在想法上又meta-了一次Smile

文章所涵蓋的範圍

Hibernate的入門大致上就是要學學如何設定config file和撰寫要被持久保存的類別及該類別的config file。為了不增加初學者的負擔,大致上會做到簡單的類別撰寫與單一個relation的情況。
更明確的範圍是,本文從http://www.hibernate.org/hib_docs/v3/reference/en/html/tutorial.html 中的1.2節內文為基礎改寫整理而來

您適合閱讀本篇文章嗎?

1. 什麼是xml ?
2. 什麼是database (你有一套自己熟悉的database system嗎?)
3. 什麼是jdbc ? (你會填jdbc connection string嗎?)
4. 什麼是java bean
5. 如何設定classpath (您知道如何加入某些.jar檔到你的classpath中嗎?)

以上的問題,只要有一項您完全不了解,也許您該先試著學習,不需要精熟,能夠正確使用即可。當然,會寫java是必備的Smile

我使用什麼工具

其實這是一個無關緊要的問題,唯一會告訴你的就是。我將使用mysql做為本次入門所用的資料庫系統,本篇也不會放上和ide相關的東西,或是ant的build.xml。因為每一個人習慣不同,只要能正確地編譯出檔案即可。

使用Hibernate流程
1.撰寫persistent class與class mapping file
2.修改Hibernate config file加入欲增加的persistent class (如果有必要的話,修改資料庫連線設定及其他參數)
3.開始使用Hibernate來寫入資料庫

開始我們的教學

首先,為了讓Hibernate知道我們要存放什麼到資料庫中我們應該撰寫persistent class,與他的class mapping file。在撰寫之前有一些默契是您必需瞭解的: 每一個persistent class都應該為Hibernate準備一個type為Long的private filed, id。而persistent class本身是一個java bean,所以java bean基本的規則也要遵守: 要有一個無引數建構子,提供型態匹配的getter與setter。

我們使用的範例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package events;
 
import java.util.Date;
 
public class Event {
        
  private Long id; // 如之前所言,我們需要一個Long id
  private String title;
  private Date date;
  
        
  public Event(){} // 以及java bean必備的無引數建構子
 
  public Date getDate() {
    return date;
  }
 
  public void setDate(Date date) {
    this.date = date;
  }
 
  public Long getId() {
    return id;
  }
 
  private void setId(Long id) {
    this.id = id;
  }
 
  public String getTitle() {
    return title;
  }
 
  public void setTitle(String title) {
    this.title = title;
  }
  
}

這個範例,我們要使用的資料表中含有3個欄位,扣除了Hibernate用的id。剩下的date與title才是我們真正要儲存的資料。相信眼尖的看倌們一定發現了,我把setId的存取權限修飾詞標為紅色。是的,這是一個private的method。因為我們不打算自己寫入他,這是Hibernate的責任,所以設為private是一個好的選擇(別為Hibernate擔心,他有辦法寫入任何權限的資料欄位)。

準備好了persistent class之後,我們要準備這class的mapping file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 
<hibernate-mapping>
  <class name="events.Event" table="EVENTS">
    <id name="id" column="EVENT_ID">
      <generator class="native" />
    </id>
    <property name="date" type="timestamp" column="EVENT_DATE"/>
    <property name="title" />
  </class>
</hibernate-mapping>

我們可以看到root element hibernate-mapping內有一個child element裡面就是要填的們persistent class的資訊。除了id自己使用id element之外,其他的欄位都由property element設定之。id自己獨立為一個element是有理由的,這樣的設計方便加入nested element generator而不失可讀性。剛剛提到id是由Hibernate來產生的,那要怎麼產生,倒是使用者能指定的,在這個範例中我們指定為native。就是利用資料庫本身提供的sequence產生id的內容。接著,我們看到我們所設定的2個資料欄位,一個是date,一個是title。其中property的屬性,name就是填入這些欄位在persistent class中的member field name。type則可指定或是交由Hibernate與Database去協調,在這裡的date有許多表示法,所以我們要指定一種資料型態。再來,肯定有人會想問: 為什麼date多了一個column屬性呢? 這column屬性,當你不填的時候,就等於你填上了與name同等的資料。但是date這個字,對許多資料庫系統來說是一個函數名稱,所以會產生意外的結果,我們最好給他另一種名稱,故需填上column欄位。
寫好了mapping file 後我們必需給他一個名稱,他的副檔名為.hbm.xml,檔名則為persistent class的名稱。依此例應為: Event.hbm.xml (請放在與Event.class同一個資料夾)

修改Hibernate config file :: hibernate.cfg.xml (放在root classpath中)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
 
    <session-factory>
 
        <!-- Database connection settings -->
        <property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=utf-8</property>
        <property name="connection.username">who</property>
        <property name="connection.password">whocare</property>
 
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>
 
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 
        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
 
        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
 
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
 
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create</property>
 
        <mapping resource="events/Event.hbm.xml"/>
 
    </session-factory>
 
</hibernate-configuration>

這是修改自Hibernate offical reference doucment的範例,請自行修改標示的部分以符合自己練習的環境。注意到html entity的使用。千萬忘別了最後一個標示出來的hbm2ddl.auto property這個屬性的用意在於當你使用Hibernate時,自動drop table並重新create table。您可以在第一次執行他時保留,就免去自行建立table的辛苦。當您不在需要時,可以註解掉或直接刪除。當然,我們一定少不了的是加上mapping resource element。

萬事俱備只欠東風
撰寫好了persistent class與mapping和Hibernate config file,接著我們就要來真正使用Hibernate來做O/R mapping的操作。
要使用Hibernate大致上是透過SessionFactory取得Session物件,透過Session物件以及persistent class做O/R mapping的操作。依手冊上的建議,我們不需要每一次都產生SessionFactory,所以運用上Singlethon Pattern是一個好的想法(直接copy & paste 手冊裡的code):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package util;
 
import org.hibernate.*;
import org.hibernate.cfg.*;
 
public class HibernateUtil {
 
    private static final SessionFactory sessionFactory;
 
    static {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            sessionFactory = new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
 
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
 
}


接著我們撰寫自己的測試檔:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// writing test
package events;
 
import java.util.Date;
 
import org.hibernate.Session;
 
import util.HibernateUtil;
 
public class HibernateTest {
  /**
   * @param args
   */
  public static void main(String[] args) {
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();
    Event e = new Event();
    e.setDate(new Date());
    e.setTitle("中文");
    session.save(e);
    session.getTransaction().commit();
    HibernateUtil.getSessionFactory().close();
 
  }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//reading test
package events;
 
import java.util.Iterator;
 
public class TestGetResult {
  static Logger log = Logger.getLogger(TestGetResult.class.getName());
 
  public static void main(String[] args) {
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();
    Iterator it =(Iterator) session.createQuery("from Event").iterate();
    while(it.hasNext()){
      Event e = (Event) it.next();
      log.info(e.getId()+" # "+ e.getDate()+ " # "+e.getTitle());
    }
    
    
    session.getTransaction().commit();
    HibernateUtil.getSessionFactory().close();
  }
}
 


整個使用上還算蠻直算的,取得Sesson後即呼叫beginTransaction,結束時也記得將transaction commit並close SessionFactory。
大致上,這就是本次的Hibernate入門教學Smile


qrtt1 edited on 2006-04-26 20:16
reply to postreply to post
» JWorld@TW »  Object Relational Mapping » Hibernate

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8