superwei

          導(dǎo)航

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          統(tǒng)計(jì)

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          Hibernate的原理與配置快速入門(1)

          也許你聽(tīng)說(shuō)過(guò)Hibernate的大名,但可能一直不了解它,也許你一直渴望使用它進(jìn)行開(kāi)發(fā),那么本文正是你所需要的!在本文中,我向大家重點(diǎn)介紹Hibernate的核心API調(diào)用庫(kù),并講解一下它的基本配置。

            看完本文后,我相信你對(duì)什么是ORM(對(duì)像/關(guān)系映射)以及它的優(yōu)點(diǎn)會(huì)有一個(gè)深刻的認(rèn)識(shí),我們先通過(guò)一個(gè)簡(jiǎn)單的例子開(kāi)始來(lái)展現(xiàn)它的威力。

            正如一些傳統(tǒng)的經(jīng)典計(jì)算機(jī)文章大都會(huì)通過(guò)一個(gè)“hello,world”的例子開(kāi)始講解一樣,我們也不例外,我們也將從一個(gè)相對(duì)簡(jiǎn)單的例子來(lái)闡述Hibernate的開(kāi)發(fā)方法,但如果要真正闡述Hibernate的一些重要思想,僅僅靠在屏幕上打印一些字符是遠(yuǎn)遠(yuǎn)不夠的,在我們的示例程序中,我們將創(chuàng)建一些對(duì)象,并將其保存在數(shù)據(jù)庫(kù)中,然后對(duì)它們進(jìn)行更新和查詢。

          “Hello World” “Hello world”示例程序讓您對(duì)Hibernate有一個(gè)簡(jiǎn)單的認(rèn)識(shí)
          理解Hibernate的架構(gòu) 介紹Hibernate接口的主要功能。
          核心接口 Hibernate有5個(gè)核心接口,通過(guò)這幾個(gè)接口開(kāi)發(fā)人員可以存儲(chǔ)和獲得持久對(duì)象,并且能夠進(jìn)行事務(wù)控制
          一個(gè)重要的術(shù)語(yǔ):Type Type是Hibernate發(fā)明者發(fā)明的一個(gè)術(shù)語(yǔ),它在整個(gè)構(gòu)架中是一個(gè)非常基礎(chǔ)、有著強(qiáng)大功能的元素,一個(gè)Type對(duì)象能將一個(gè)Java類型映射到數(shù)據(jù)庫(kù)中一個(gè)表的字段中去。
          策略接口 Hibernate與某些其它開(kāi)源軟件不同的還有一點(diǎn)――高度的可擴(kuò)展性,這通過(guò)它的內(nèi)置策略機(jī)制來(lái)實(shí)現(xiàn)。
          基礎(chǔ)配置 Hibernate可以配置成可在任何Java環(huán)境中運(yùn)行,一般說(shuō)來(lái),它通常被用在2-3層的C/S模式的項(xiàng)目中,并被部署在服務(wù)端。
          創(chuàng)建一個(gè)SessionFactory對(duì)象 要?jiǎng)?chuàng)建一個(gè)SessionFactory對(duì)象,必須在Hibernate初始化時(shí)創(chuàng)建一個(gè)Configuration類的實(shí)例,并將已寫(xiě)好的映射文件交由它處理。

            “Hello World”

            Hibernate應(yīng)用程序定義了一些持久類,并且定義了這些類與數(shù)據(jù)庫(kù)表格的映射關(guān)系。在我們這個(gè)“Hello world”示例程序中包含了一個(gè)類和一個(gè)映射文件。讓我們看看這個(gè)簡(jiǎn)單的持久類包含有一些什么?映射文件是怎樣定義的?另外,我們?cè)撛鯓佑肏ibernate來(lái)操作這個(gè)持久類。

            我們這個(gè)簡(jiǎn)單示例程序的目的是將一些持久類存儲(chǔ)在數(shù)據(jù)庫(kù)中,然后從數(shù)據(jù)庫(kù)取出來(lái),并將其信息正文顯示給用戶。其中Message正是一個(gè)簡(jiǎn)單的持久類:,它包含我們要顯示的信息,其源代碼如下:

            列表1 Message.Java 一個(gè)簡(jiǎn)單的持久類

          package hello;
          public class Message {
           private Long id;
           private String text;
           private Message nextMessage;
           private Message() {}
           public Message(String text) {
            this.text = text;
           }
           public Long getId() {
            return id;
           }
           private void setId(Long id) {
            this.id = id;
           }
           public String getText() {
            return text;
           }
           public void setText(String text) {
            this.text = text;
           }
           public Message getNextMessage() {
            return nextMessage;
           }
           public void setNextMessage(Message nextMessage) {
            this.nextMessage = nextMessage;
           }
          }


            Message類有三個(gè)屬性:Message的id 、消息正文、以及一個(gè)指向下一條消息的指針。其中id屬性讓我們的應(yīng)用程序能夠唯一的識(shí)別這條消息,通常它等同于數(shù)據(jù)庫(kù)中的主鍵,如果多個(gè)Message類的實(shí)例對(duì)象擁有相同的id,那它們代表數(shù)據(jù)庫(kù)某個(gè)表的同一個(gè)記錄。在這里我們選擇了長(zhǎng)整型作為我們的id值,但這不是必需的。Hibernate允許我們使用任意的類型來(lái)作為對(duì)象的id值,在后面我們會(huì)對(duì)此作詳細(xì)描述。

            你可能注意到Message類的代碼類似于JavaBean的代碼風(fēng)格,并且它有一個(gè)沒(méi)有參數(shù)的構(gòu)造函數(shù),在我們以后的代碼中我將繼續(xù)使用這種風(fēng)格來(lái)編寫(xiě)持久類的代碼。

            Hibernate會(huì)自動(dòng)管理Message類的實(shí)例,并通過(guò)內(nèi)部機(jī)制使其持久化,但實(shí)際上Message對(duì)象并沒(méi)有實(shí)現(xiàn)任何關(guān)于Hibernate的類或接口,因此我們也可以將它作為一個(gè)普通的Java類來(lái)使用:

          Message message = new Message("Hello World");
          System.out.println( message.getText() );


            以上這段代碼正是我們所期望的結(jié)果:它打印“hello world”到屏幕上。但這并不是我們的最終目標(biāo);實(shí)際上Hibernate與諸如EJB容器這樣的環(huán)境在持久層實(shí)現(xiàn)的方式上有很大的不同。我們的持久類(Message類)可以用在與容器無(wú)關(guān)的環(huán)境中,不像EJB必須要有EJB容器才能執(zhí)行。為了能更清楚地表現(xiàn)這點(diǎn),以下代碼將我們的一個(gè)新消息保存到數(shù)據(jù)庫(kù)中去:

          Session session = getSessionFactory().openSession();
          Transaction tx = session.beginTransaction();
          Message message = new Message("Hello World");
          session.save(message);
          tx.commit();
          session.close();


            以上這段代碼調(diào)用了Hibernate的Session和Transaction接口(關(guān)于getSessionFactory()方法我們將會(huì)馬上提到)。它相當(dāng)于我們執(zhí)行了以下SQL語(yǔ)句:

          insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
          values (1, 'Hello World', null)


            在以上的SQL語(yǔ)句中,MESSAGE_ID字段到底被初始化成了什么值呢?由于我們并沒(méi)有在先前的代碼中為message對(duì)象的id屬性賦與初始值,那它是否為null呢?實(shí)際上Hibernate對(duì)id屬性作了特殊處理:由于它是一個(gè)對(duì)象的唯一標(biāo)識(shí),因此當(dāng)我們進(jìn)行save()調(diào)用時(shí),Hibernate會(huì)為它自動(dòng)賦予一個(gè)唯一的值(我們將在后面內(nèi)容中講述它是如何生成這個(gè)值的)。

            我們假設(shè)你已經(jīng)在數(shù)據(jù)庫(kù)中創(chuàng)建了一個(gè)名為MESSAGE的表,那么既然前面這段代碼讓我們將Message對(duì)象存入了數(shù)據(jù)庫(kù)中,那么現(xiàn)在我們就要將它們一一取出來(lái)。下面這段代碼將按照字母順序,將數(shù)據(jù)庫(kù)中的所有Message對(duì)象取出來(lái),并將它們的消息正文打印到屏幕上:

          Session newSession = getSessionFactory().openSession();
          Transaction newTransaction = newSession.beginTransaction();
          List messages =newSession.find("from Message as m order by m.text asc");
          System.out.println( messages.size() + " message(s) found:" );
          for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
           Message message = (Message) iter.next();
           System.out.println( message.getText() );
          }
          newTransaction.commit();
          newSession.close();


            在以上這段代碼中,你可能被find()方法的這個(gè)參數(shù)困擾著:"from Message as m order by m.text asc",其實(shí)它是Hibernate自己定義的查詢語(yǔ)言,全稱叫Hibernate Query Language(HQL)。通俗地講HQL與SQL的關(guān)系差不多就是方言與普通話之間的關(guān)系,咋一看,你會(huì)覺(jué)得它有點(diǎn)類似于SQL語(yǔ)句。其實(shí)在find()調(diào)用時(shí),Hibernate會(huì)將這段HQL語(yǔ)言翻譯成如下的SQL語(yǔ)句:

          select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
          from MESSAGES m
          order by m.MESSAGE_TEXT asc


            以下就是運(yùn)行結(jié)果:

          1 message(s) found:
          Hello World


            如果你以前沒(méi)有ORM(對(duì)象-關(guān)系映射)的開(kāi)發(fā)經(jīng)驗(yàn),那你可能想在代碼的某個(gè)地方去尋找這段SQL語(yǔ)句,但在Hibernate中你可能會(huì)失望:它根本不存在!所有就SQL語(yǔ)句都是Hibernate動(dòng)態(tài)生成的。

            也許你會(huì)覺(jué)得還缺點(diǎn)什么,對(duì)!僅憑以上代碼Hibernate是無(wú)法將我們的Message類持久化的。我們還需要一些更多的信息,這就是映射定義表!這個(gè)表在Hibernate中是以XML格式來(lái)體現(xiàn)的,它定義了Message類的屬性是怎樣與數(shù)據(jù)庫(kù)中的MESSAGES表的字段進(jìn)行一一對(duì)應(yīng)的,列表2是這個(gè)示例程序的映射配置文件清單:

            列表2:示例程序的對(duì)象-關(guān)系映射表

          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
          <hibernate-mapping>
          <class name="hello.Message" table="MESSAGES">
           <id name="id" column="MESSAGE_ID">
            <generator class="increment"/>
           </id>
           <property name="text" column="MESSAGE_TEXT"/>
           <many-to-one name="nextMessage" cascade="all" column="NEXT_MESSAGE_ID"/>
          </class>
          </hibernate-mapping>


            以上這個(gè)文檔告訴Hibernate怎樣將Message類映射到MESSAGES表中,其中Message類的id屬性與表的MESSAGE_ID字段對(duì)應(yīng),text屬性與表的MESSAGE_TEXT字段對(duì)應(yīng),nextMessage屬性是一個(gè)多對(duì)一的關(guān)系,它與表中的NEXT_MESSAGE_ID相對(duì)應(yīng)。

            相對(duì)于有些開(kāi)源項(xiàng)目來(lái)說(shuō),Hibernate的配置文件其實(shí)是很容易理解的。你可以輕松地修改與維護(hù)它。只要你定義好了持久類與數(shù)據(jù)庫(kù)中表字段的對(duì)應(yīng)關(guān)系就行了,Hibernate會(huì)自動(dòng)幫你生成SQL語(yǔ)句來(lái)對(duì)Message對(duì)象進(jìn)行插入、更新、刪除、查找工作,你可以不寫(xiě)一句SQL語(yǔ)句,甚至不需要懂得SQL語(yǔ)言!

            現(xiàn)在讓我們做一個(gè)新的試驗(yàn),我們先取出第一個(gè)Message對(duì)象,然后修改它的消息正文,最后我們?cè)偕梢粋€(gè)新的Message對(duì)象,并將它作為第一個(gè)Message對(duì)象的下一條消息,其代碼如下:

            列表3 更新一條消息

          Session session = getSessionFactory().openSession();
          Transaction tx = session.beginTransaction();
          // 1 is the generated id of the first message
          Message message =(Message) session.load( Message.class, new Long(1) );
          message.setText("Greetings Earthling");
          Message nextMessage = new Message("Take me to your leader (please)");
          message.setNextMessage( nextMessage );
          tx.commit();
          session.close();


            以上這段代碼在調(diào)用時(shí),Hibernate內(nèi)部自動(dòng)生成如下的SQL語(yǔ)句:

          select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
          from MESSAGES m
          where m.MESSAGE_ID = 1

          insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
          values (2, 'Take me to your leader (please)', null)

          update MESSAGES
          set MESSAGE_TEXT = 'Greetings Earthling', NEXT_MESSAGE_ID = 2
          where MESSAGE_ID = 1


            當(dāng)?shù)谝粋€(gè)Message對(duì)象的text屬性和nextMessage被程序修改時(shí),請(qǐng)注意Hibernate是如何檢測(cè)到這種變化,并如何在數(shù)據(jù)庫(kù)中自動(dòng)對(duì)它更新的。這實(shí)際上是Hibernate的一個(gè)很有價(jià)值的特色,我們把它稱為“自動(dòng)臟數(shù)據(jù)檢測(cè)”,Hibernate的這個(gè)特色使得當(dāng)我們修改一個(gè)持久對(duì)象的屬性后,不必顯式地通知Hibernate去將它在數(shù)據(jù)庫(kù)中進(jìn)行更新。同樣的,當(dāng)?shù)谝粋€(gè)Message對(duì)象調(diào)用setNextMessage()方法將第二個(gè)Message對(duì)象作為它的下一條消息的引用時(shí),第二條消息會(huì)無(wú)需調(diào)用save()方法,便可以自動(dòng)地保存在數(shù)據(jù)庫(kù)中。這種特色被稱為“級(jí)聯(lián)保存”,它也免去了我們顯式地對(duì)第二個(gè)Message對(duì)象調(diào)用save()方法之苦。

            如果我們?cè)龠\(yùn)行先前的那段將數(shù)據(jù)庫(kù)中所有的Message對(duì)象都打印出來(lái)的代碼,那它的運(yùn)行結(jié)果如下:

          2 message(s) found:
          Greetings Earthling
          Take me to your leader (please)


            “Hello world”示例程序現(xiàn)在介紹完畢。我們總算對(duì)Hibernate有了一個(gè)簡(jiǎn)單的認(rèn)識(shí),下面我們將回過(guò)頭來(lái),對(duì)Hibernate的主要API調(diào)用作一下簡(jiǎn)要的介紹:

          posted on 2005-10-31 11:29 小辭猬 閱讀(275) 評(píng)論(0)  編輯  收藏 所屬分類: JAVA

          主站蜘蛛池模板: 东乡| 巫山县| 海宁市| 鹤山市| 浮梁县| 苏尼特左旗| 长寿区| 无为县| 聂拉木县| 宜兴市| 周口市| 大荔县| 黄骅市| 日照市| 和平县| 海口市| 伊通| 察隅县| 息烽县| 贵港市| 德钦县| 旌德县| 武鸣县| 平阳县| 永昌县| 高安市| 佳木斯市| 贵定县| 建宁县| 沙坪坝区| 宝山区| 自贡市| 太原市| 琼海市| 南投县| 文安县| 巴彦县| 南安市| 贵港市| 灵山县| 武隆县|