以前大多數(shù)時(shí)間都是做.NET,對(duì)JAVA的開(kāi)源框架這塊就簡(jiǎn)單的了解了下,沒(méi)怎么認(rèn)真的學(xué)習(xí)過(guò),從今天開(kāi)始我又將參與一個(gè)J2EE的項(xiàng)目,因公司的同事幾乎全是.NET,今天就和同事一起學(xué)習(xí)Hibernate這玩意,簡(jiǎn)單記錄些筆記于此,以便以后方便查看,也給初學(xué)Hibernate的朋友一點(diǎn)參考.文章中我會(huì)將理論和實(shí)例結(jié)合.

一、初識(shí)Hibernate
       Hibernate是........這個(gè)我就不多說(shuō)了,網(wǎng)上到處都可以搜索到.
  
 二、配置Hibernate開(kāi)發(fā)環(huán)境
       在開(kāi)發(fā)Hibernate應(yīng)用的時(shí)候需要預(yù)先把相應(yīng)的JAR包配置到CLASS_PATH,我使用的是MyEclipse作為開(kāi)發(fā)工具,主要的JAR大致如下:
       ---antlr.jar
       ---cglib.jar
       ---asm.jar
       ---asm-attrs.jar
       ---commons-collections.jar
       ---commons-logging.jar
       ---ehcache.jar
       ---hibernate3.jar
       ---jta.jar
       ---dom4j.jar
       ---log4j.jar
       這些包從何來(lái),它們都可以從Hibernate網(wǎng)站下載的Hibernate發(fā)布包里找到,在lib目錄下。
       另外就是還需要一個(gè)連接數(shù)據(jù)庫(kù)的驅(qū)動(dòng),我使用的是Oracle數(shù)據(jù)庫(kù)。

三、開(kāi)發(fā)Hibernate程序的步驟
      開(kāi)發(fā)Hibernate程序通常分為下面這幾步:
      1、 建立JavaBean--> 每個(gè)JavaBean必須提供一個(gè)無(wú)參的構(gòu)造函數(shù),并為private屬性提供get/set訪問(wèn)方法。如下:
 1 package day.one;
 2 
 3 public class Person {
 4     private int id;
 5     private String name;
 6     private int age;
 7     private String phone;
 8     
 9     public int getAge() {
10         return age;
11     }
12 
13     public void setAge(int age) {
14         this.age = age;
15     }
16 
17     public int getId() {
18         return id;
19     }
20 
21     public void setId(int id) {
22         this.id = id;
23     }
24 
25     public String getName() {
26         return name;
27     }
28 
29     public void setName(String name) {
30         this.name = name;
31     }
32 
33     public String getPhone() {
34         return phone;
35     }
36 
37     public void setPhone(String phone) {
38         this.phone = phone;
39     }
40 
41     public Person() {    
42     }
43 
44     public Person(String name, int age, String phone) {
45         super();
46         this.name = name;
47         this.age = age;
48         this.phone = phone;
49     }
50 }

        2、編寫(xiě)映射文件(*.hbm.xml)-->這一步在Hibernate開(kāi)發(fā)中最為重要,工作量是很大的。詳細(xì)配置格式可查看Hibernate包下的src/org/hibernate/hibernate-mapping-3.0.dtd,下面代碼塊便是上面Person的配置文件:

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 5     
 6 <hibernate-mapping package="day.one">
 7     <class name="Person" table="t_Person">
 8         <id name="id" column="id" unsaved-value="-1">
 9                 <!--主建生成策略  -->
10             <generator class="sequence">
11                  <param name="sequence">Person_id_seq</param>
12              </generator>
13         </id>
14      <!--當(dāng)屬性名與表的字段名相同時(shí),可以確省column屬性配置-->
15      <property name="name" column="name" />  
16      <property name="age" />
17      <property name="phone"/>
18     </class>
19 </hibernate-mapping>

    3、創(chuàng)建數(shù)據(jù)表與主鍵生成的Sequence
        上面Person這個(gè)JavaBean已經(jīng)建立好了,并寫(xiě)好了相應(yīng)的配置文件,現(xiàn)在就需要把對(duì)應(yīng)的數(shù)據(jù)庫(kù)表建立好,我使用的是Oracle數(shù)據(jù)庫(kù),建表和建立主鍵生成的Sequence的命令如下:
 1 --創(chuàng)建t_Person表
 2 create table t_Person
 3 (
 4  id number(7primary key,
 5  name varchar2(30not null,
 6  age number(4not null,
 7  phone varchar2(20)
 8 );
 9 
10 --創(chuàng)建t_Person的主鍵生成Sequence
11 create sequence person_id_seq;
12 select * from t_person;

        4、編寫(xiě)Hibernate配置文件(hibernate.cfg.xml)-->詳細(xì)配置格式可查看Hibernate包下的src/org/hibernate/hibernate-configuration-3.0.dtd文件,里面有詳細(xì)的描述。下邊是Hibernate的配置文件的簡(jiǎn)單結(jié)構(gòu):
1 <hibernate-configuration>
2    <session-factory>
3      <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
4            <!--詳細(xì)配置信息可查看Hibernate包下的etc/hibernate.properties -->
5    </session-factory>
6 <hibernate-configuration>

        下面便是我配置的一個(gè)完整(相對(duì)完整,僅供參考)的Hibernate的配置文件,如下:
Hibernate配置文件

        4、創(chuàng)建配置(Configuration)
             Configuration cfg = new Configuration().configure();
     
         5、 構(gòu)建會(huì)話工廠(SessionFactory)
             SessionFactory = cfg.buildSessionFactory();
     
          6、打開(kāi)會(huì)話(session)
              Session session = sf.openSession();
      
          7、啟動(dòng)事務(wù)(Transaction)
              Transaction ts = session.beginTransaction();

          8、持久化操作(CUQD)
              session.save(*);  *表示一個(gè)對(duì)象
              session.update(*);
              session.delete(*);
              ..........................................
     
          9、提交事務(wù)(commit)
                  ts.commit();
      
          10、事務(wù)回滾(rollback)
                 ts.rollback();

四、第一個(gè)Hibernate程序
需要持久化的實(shí)體類

Hibernate映射文件

Hibernate配置文件

操作客戶端

五、Hibernate映射過(guò)程分析
        如上就完成了對(duì)一個(gè)簡(jiǎn)單的對(duì)象的持久化操作,將構(gòu)造好的Person對(duì)象通過(guò)Hibernate持久化操作到數(shù)據(jù)庫(kù)。OK,下面我們來(lái)簡(jiǎn)單的分析下Hibernate做持久化的過(guò)程,他是怎么來(lái)完成映射的呢?
1 11:29:36,562  INFO HbmBinder:300 - Mapping class: day.one.Person -> t_Person
2 11:29:36,593 DEBUG HbmBinder:1270 - Mapped property: id -> id
3 11:29:36,609 DEBUG HbmBinder:1270 - Mapped property: name -> name
4 11:29:36,609 DEBUG HbmBinder:1270 - Mapped property: age -> age
5 11:29:36,609 DEBUG HbmBinder:1270 - Mapped property: phone -> phone

        上面這幾行輸入信息是在運(yùn)行的時(shí)候輸出的,詳細(xì)可以查看控制臺(tái)的輸出信息。我們可以看出,Hibernate他在中間做了些什么工作呢?
        1、將day.one.Person這個(gè)類映射到了數(shù)據(jù)庫(kù)的t_Person表,而這正是我們?cè)谟成湮募型ㄟ^(guò)table屬性來(lái)配置的,如下,將Person這個(gè)持久化類映射到數(shù)據(jù)庫(kù)的t_Person表:
1 <class name="Person" table="t_Person">

        2、后面四行DEBUG輸出的內(nèi)容我想就不用多說(shuō)了,也就是把映射文件里配置的property影射到數(shù)據(jù)庫(kù)指定的字段:
1<!--id特殊,不使用property,hibernate為id的映射提供了專用的標(biāo)記"id"-->
2<id name="id" column="id" unsaved-value="-1">
3
4<!--當(dāng)屬性名與表的字段名相同時(shí),可以確省column屬性配置-->
5<property name="name" column="name" />  
6<property name="age" />
7<property name="phone"/>
8
9

六、Hibernate持久化原理分析
        我們可以查看程序運(yùn)行時(shí)輸入的DEBUG信息,下面是截取的一部分:
1 selectselect id from t_Person where id =?
2 selectselect person_.id, person_.name as name0_, person_.age as age0_, person_.phone as phone0_ from t_Person person_ 
                where
 person_.id=?
3 Insert 0insert into t_Person (name, age, phone, id) values (?, ?, ?, ?)
4 Update 0update t_Person set name=?, age=?, phone=where id=?
5 Delete 0delete from t_Person where id=?
        當(dāng)Hibernate成功完成映射后,表會(huì)為我們的持久化對(duì)象生成如上的相關(guān)SQL語(yǔ)句,這一步就是為后面做持久化操作做準(zhǔn)備。我們?cè)谟成渑渲梦募镏付ǖ膇d生成策略為Sequence,這時(shí)Hibernate 就會(huì)先到數(shù)據(jù)庫(kù)里去將指定的sequence查詢出來(lái)賦值給持久化對(duì)象的id屬性,然后在做其他的持久化操作。生成的查詢語(yǔ)句如下:
 1 SQL:393 - 
 2     select
 3         Person_id_seq.nextval 
 4     from
 5         dual
 6 Hibernate: 
 7     select
 8         Person_id_seq.nextval 
 9     from
10         dual

        最終做持久化操作的時(shí)候便會(huì)條用上面所生成的SQL語(yǔ)句,Hibernate的底層在去通過(guò)JDBC完成數(shù)據(jù)庫(kù)的相關(guān)操作。就本文前的實(shí)例程序,我們是將構(gòu)造的Person對(duì)象持久化到數(shù)據(jù)庫(kù),那么他調(diào)用的SQL就如下:
 1SQL:393 - 
 2    insert 
 3    into
 4        t_Person
 5        (name, age, phone, id) 
 6    values
 7        (?, ?, ?, ?)
 8Hibernate: 
 9    insert 
10    into
11        t_Person
12        (name, age, phone, id) 
13    values
14        (?, ?, ?, ?)


        OK,下面我們?cè)趤?lái)做一個(gè)查詢的操作,將剛剛通過(guò)session.save(person)到數(shù)據(jù)庫(kù)的這條記錄查詢出來(lái),看看DEBUG出的SQL語(yǔ)句是什么樣的:

 1 SQL:393 - 
 2     select
 3         person0_.id as id0_0_,
 4         person0_.name as name0_0_,
 5         person0_.age as age0_0_,
 6         person0_.phone as phone0_0_ 
 7     from
 8         t_Person person0_ 
 9     where
10         person0_.id=?
11 Hibernate: 
12     select
13         person0_.id as id0_0_,
14         person0_.name as name0_0_,
15         person0_.age as age0_0_,
16         person0_.phone as phone0_0_ 
17     from
18         t_Person person0_ 
19     where
20         person0_.id=?

        現(xiàn)在就很容易看出了,無(wú)論是做什么樣的持久化操作,他都是圍繞著映射后所生成的SQL來(lái)處理的,其實(shí)這里的關(guān)鍵還是映射文件,映射文件配置好了,用Hibernate做持久化就不在是什么難事了。

本文就介紹于此,下一篇將介紹使用Hibernate來(lái)做一對(duì)一(OneToOne)的關(guān)系影射。

注:原創(chuàng)文章版權(quán)歸作者,歡迎轉(zhuǎn)載,未經(jīng)作者同意必須注明文章出處或在頁(yè)面適當(dāng)位置給出原文連接,謝謝!
        文章出處:http://beniao.blogjava.net      作者:Beniao       時(shí)間:2008.08.14
        我的.NET技術(shù)博客:http://beniao.cnblogs.com