4.2 Hibernate應用基礎

1.Hibernate應用實例開發

1)創建數據庫及表

    本書使用SQL Server 2005數據庫。在XSCJ數據庫中創建KCB表。java

表名:KCB算法

項目名sql

列名數據庫

數據類型數組

是否可空瀏覽器

默認值緩存

說明安全

課程號session

KCH數據結構

char(3)



主鍵

課程名

KCM

char(20)



開學學期

KXXQ

smallint


只能爲1-8

學時

XS

int

0


學分

XF

int

0


2)在MyEclipse中建立對SQL Server 的鏈接

    啓動MyEclipse,選擇【Window】→【Open Perspective】→【MyEclipse Database Explorer】菜單項,打開MyEclipse Database瀏覽器,右擊菜單,如圖4.2所示,選擇【New…】菜單項,出現如圖4.3所示的對話框,編輯數據庫鏈接驅動。

    填寫要創建的鏈接的名稱「MyConn」(自定義),鏈接數據庫的URL「jdbc:sqlserver://localhost:1433;databaseName=XSCJ」,填寫數據庫的用戶名和密碼添加數據庫驅動

圖4.2  MyEclipse Database瀏覽器,建立一個新的鏈接


圖4.3  編輯數據庫鏈接驅動

 

    編輯完成之後,在MyEclipse Database瀏覽器中,右擊剛纔建立的MyConn數據庫鏈接,選擇「Open connection…」菜單項,打開名爲「MyConn」的數據鏈接,如圖4.4所示。

圖4.4  打開數據庫鏈接

 

3)建立Web項目,命名爲「HibernateTest」

4)添加Hibernate開發能力

    右擊項目名HibernateTest,選擇【MyEclipse】→【Add Hibernate Capabilites】菜單項,出現如圖4.5所示的對話框,選擇Hibernate框架應用版本及所須要的類庫

圖4.5  選擇Hibernate版本及所需Jar包

    單擊【Next】按鈕,進入如圖4.6所示界面。建立Hibernate配置文件hibernate.cfg.xml,將該文件放在src文件夾下,後面會詳細介紹該文件內容。這裏先說明添加Hibernate開發功能的步驟。

圖4.6  建立配置文件hibernate.cfg.xml

 

    單擊【Next】按鈕,進入如圖4.7所示界面,指定Hibernate數據庫鏈接細節。因爲在前面已經配置一個名爲MyConn的數據庫鏈接,因此這裏只須要選擇DB Driver爲「MyConn」便可。

圖4.7  指定hibernate數據庫鏈接

 

    單擊【Next】按鈕,出現如圖4.8所示界面。Hibernate中有一個與數據庫打交道重要的類Session。而這個類是由工廠SessionFactory建立的。這個界面詢問是否須要建立SessionFactory類。若是須要建立,還須要指定建立的位置和類名。這些接口都會在後面詳細介紹。單擊【Finish】按鈕,完成Hibernate的配置。

圖4.8  建立SessionFactory類來簡化Hibernate會話處理


5)生成數據庫表對應的Java類對象和映射文件

    首先在MyEclispse下建立一個名爲「org.model」的包,這個包將用來存放與數據庫表對應的Java類POJO

 

    打開MyEclipse Database Explorer視圖。打開前面建立的MyConn數據鏈接,選擇【XSCJ】→【dbo】→【TABLE】菜單項,右擊KCB表,選擇【Hibernate Reverse Engineering…】菜單項,如圖4.9所示,將啓動Hibernate Reverse Engineering嚮導,該向導用於完成從已有的數據庫表生成對應的Java類和相關映像文件的配置工做。

 

圖4.9  Hibernate反向工程菜單

    

    首先,選擇生成的Java類和映像文件所在的位置,如圖4.10所示。POJOPlain Old Java Object,簡單的Java對象),一般也稱爲VOValue Object,值對象)。 使用POJO名稱是爲了避免和EJB混淆起來,其中有一些屬性及getter、setter方法。固然,若是有一個簡單的運算屬性也是能夠的,但不容許有業務方法

圖4.10  生成Hibernate映射文件和Java類

 

   單擊【Next】按鈕,進入如圖4.11所示的界面,選擇主鍵生成策略

圖4.11  配置反向工程細節

 

    點擊【Finish】,org.model包中會出現Kcb.java類和Kcb.hbm.xml。而後在hibernate.cfg.xml文件中配置映射文件<mapping resource="org/model/Kcb.hbm.xml"/>,該語句放在<session-factory>和</session-factory>之間

 

6)建立測試類

    在src文件夾下建立包test,在該包下創建測試類,命名爲Test.java,其代碼。

package test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.model.Kcb;
import org.util.HibernateSessionFactory;
 
public class Test {
 
    public static void main(String[] args) {
        // 調用HibernateSessionFactory的getSession方法建立Session對象
        Session session = HibernateSessionFactory.getSession();
        // 建立事務對象
        Transaction ts = session.beginTransaction();
        Kcb kc = new Kcb(); // 建立POJO類對象
        kc.setKch("198"); // 設置課程號
        kc.setKcm("機電"); // 設置課程名
        kc.setKxxq(new Short((short) 5)); // 設置開學學期
        kc.setXf(new Integer(5)); // 設置學分
        kc.setXs(new Integer(59)); // 設置學時
        // 保存對象
        session.save(kc);
        ts.commit(); // 提交事務
        Query query = session.createQuery("from Kcb where kch=198");
        List list = query.list();
        Kcb kc1 = (Kcb) list.get(0);
        System.out.println(kc1.getKcm());
        HibernateSessionFactory.closeSession(); // 關閉Session
    }
 
}

 

7)運行

        由於該程序爲Java Application,因此能夠直接運行。運行程序,控制檯就會打印出「機電」。在徹底沒有操做數據庫的狀況下,就完成了對數據的插入。下面將詳細講解各文件的做用。

 

2.Hibernate各類文件的做用

1)POJO類和其映射配置文件

    POJO類以下:

package org.model;
 
public class Kcb implements java.io.Serializable {
 
    private String kch; // 對應表中KCH字段
    private String kcm; // 對應表中KCM字段
    private Short kxxq; // 對應表中KXXQ字段
    private Integer xs; // 對應表中XS字段
    private Integer xf; // 對應表中XF字段
 
    public Kcb() {
    }
    // 上述屬性的getter和setter方法
 
}

    能夠發現,該類中的屬性和表中的字段是一一對應的。那麼經過什麼方法把它們一一映射起來呢?就是前面提到的*.hbm.xml映射文件。這裏固然就是Kcb.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
  PUBLIC '-//Hibernate/Hibernate Mapping DTD 3.0//EN'
  'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>
<hibernate-mapping>
    <!-- name指定POJO類,table指定對應數據庫的表 -->
    <class name="org.model.Kcb" table="KCB">
        <!-- name指定主鍵,type主鍵類型 -->
        <id name="kch" type="java.lang.String">
            <column length="3" name="KCH"/>
            <!-- 主鍵生成策略 -->
            <generator class="assigned"/>
        </id>
        <!-- POJO屬性及表中字段的對應 -->
        <property name="kcm" type="java.lang.String">
            <column length="12" name="KCM"/>
        </property>
        <property name="kxxq" type="java.lang.Short">
            <column name="KXXQ"/>
        </property>
        <property name="xs" type="java.lang.Integer">
            <column name="XS"/>
        </property>
        <property name="xf" type="java.lang.Integer">
            <column name="XF"/>
        </property>
    </class>
</hibernate-mapping>

 

    該配置文件大體分爲3個部分:

    (1)類、表映射配置

<class name="org.model.Kcb" table="KCB">

name屬性指定POJO類爲org.model.Kcb,table屬性指定當前類對應數據庫表KCB。

 

    (2)id映射配置

<id name="kch" type="java.lang.String">
    <column name="KCH" length="3" />
    <generator class="assigned" />
</id>

id節點定義實體類的標誌assigned),在這裏也就是對應數據庫表主鍵的類屬性。<generator class="assigned" />指定主鍵的生成方式

 

    Hibernate的主鍵生成策略分爲三大類Hibernate對主鍵id賦值、應用程序自身對id賦值、由數據庫對id賦值。

  • assigned應用程序自身對id賦值。當設置<generator class="assigned"/>時,應用程序自身須要負責主鍵id的賦值。例以下述代碼:

Kcb kc=new Kcb();    // 建立POJO類對象
kc.setKch("198");    // 設置課程號
kc.setKcm("機電");    // 設置課程名
kc.setKxxq(new Integer(5).shortValue());    // 設置開學學期
kc.setXf(new Integer(4).shortValue());    // 設置學分
kc.setXs(new Integer(59).shortValue());     // 設置學時
  • native:由數據庫對id賦值。當設置<generator class="native"/>時,數據庫負責主鍵id的賦值,最多見的是int型的自增型主鍵

  • hilo:經過hi/lo算法實現的主鍵生成機制須要額外的數據庫表保存主鍵生成歷史狀態

  • seqhilo與hi/lo相似經過hi/lo算法實現的主鍵生成機制,只是主鍵歷史狀態保存在sequence中,適用於支持sequence的數據庫,如Oracle

  • increment:主鍵按數值順序遞增。此方式的實現機制爲在當前應用實例中維持一個變量,以保存當前的最大值,以後每次須要生成主鍵的時候將此值加1做爲主鍵。當有多個實例訪問同一數據庫時,可能形成主鍵重複異常

  • identity:採用數據庫提供的主鍵生成機制,如SQL Server、MySQL中的自增主鍵生成機制。

  • sequence:採用數據庫提供的sequence機制生成主鍵,如Oracle sequence。

  • uuid.hex:由Hibernate基於128位惟一值產生算法根據當前設備IP、時間、JVM啓動時間、內部自增量等4個參數生成十六進制數值(編碼後長度爲32位的字符串表示)做爲主鍵。即便是在多實例併發運行的狀況下,這種算法在最大程度上保證了產生id的惟一性。固然,重複的機率在理論上依然存在,只是機率比較小。

  • uuid.string:與uuid.hex相似,只是對生成的主鍵進行編碼(長度16位)。

  • foreign:使用外部表的字段做爲主鍵

  • selectHibernate 3新引入的主鍵生成機制,主要針對遺留系統的改造工程

    (3)屬性、字段映射配置

    屬性、字段映射將映射類屬性與庫表字段相關聯。

<property name="kcm" type="java.lang.String">
           <column name="KCM" length="12" />
</property>

    name="kcm" 指定映像類中的屬性名爲「kcm」,此屬性將被映像到指定的庫表字段KCM。type="java.lang.String"指定映像字段的數據類型。column name="KCM"指定類的kcm屬性映射KCB表中的KCM字段。

 

2)hibernate.cfg.xml文件

    該文件是Hibernate重要的配置文件,配置該文件主要是配置SessionFractory類

<?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>
        <!-- 數據庫鏈接的URL -->
        <property name="connection.url">jdbc:sqlserver://localhost:1433;databaseName=XSCJ</property>
        <!-- 數據庫鏈接的用戶名,此處爲本身數據庫的用戶名和密碼 -->
        <property name="connection.username">liuyanbo</property>
        <!-- 數據庫鏈接的密碼 -->
        <property name="connection.password">123456</property>
        <!-- SQL方言,這裏使用的是SQL Server -->
        <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
        <!-- 使用的數據庫的鏈接,咱們建立的MyConn -->
        <property name="myeclipse.connection.profile">MyConn</property>
        <!-- 數據庫JDBC驅動程序 -->
        <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <!-- 表和類對應的映射文件,若是多個,都要在這裏註冊 -->
        <mapping resource="org/model/Kcb.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

    Hibernate配置文件主要用於配置數據庫鏈接Hibernate運行時所須要的各類屬性。Hibernate初始化期間會自動在CLASSPATH中尋找這個文件,並讀取其中的配置信息,爲後期數據庫操做作好準備。

 

3)HibernateSessionFactory

    HibernateSessionFactory類是自定義的SessionFactory名字能夠自定義。這裏用的HibernateSessionFactory。

package org.util;
 
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
 
public class HibernateSessionFactory {
 
    // 定義一個靜態字符串變量存放Hibernate的配置文件名
    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
    // 建立一個線程局部變量對象
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    // 建立一個靜態的Configuration對象
    private static Configuration configuration = new Configuration();
    // 定義一個靜態的SessionFactory對象
    private static org.hibernate.SessionFactory sessionFactory;
    private static String configFile = CONFIG_FILE_LOCATION;
    // 根據配置文件獲得SessionFactory對象
 
    static {
        try {
            // 獲得configuration對象
            // 該句和上面建立的靜態對象合起來就爲
            // configuration=new Configuration().configure(configFile);
            configuration.configure(configFile);
            sessionFactory = configuration.buildSessionFactory();
        } catch (Exception e) {
            System.err.println("%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }
    private HibernateSessionFactory() {
    }
 
    // 取得Session對象
    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession()
                    : null;
            threadLocal.set(session);
        }
        return session;
    }
 
    // 能夠調用該方法從新建立SessionFactory對象
    public static void rebuildSessionFactory() {
        try {
            configuration.configure(configFile);
            sessionFactory = configuration.buildSessionFactory();
        } catch (Exception e) {
            System.err.println("%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }
 
    // 關閉Session
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            session.close();
        }
    }
 
    public static org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    }
 
    public static void setConfigFile(String configFile) {
        HibernateSessionFactory.configFile = configFile;
        sessionFactory = null;
    }
 
    public static Configuration getConfiguration() {
        return configuration;
    }
 
}

在Hibernate中,Session負責完成對象持久化操做該文件負責建立Session對象,以及關閉Session對象。從該文件能夠看出,Session對象的建立大體須要如下3個步驟:

① 初始化Hibernate配置管理類Configuration

② 經過Configuration類實例建立Session的工廠類SessionFactory

③ 經過SessionFactory獲得Session實例

3.Hibernate核心接口

1)Configuration接口

    Configuration負責管理Hibernate的配置信息。Hibernate運行時須要一些底層實現的基本信息。這些信息包括:數據庫URL、數據庫用戶名、數據庫用戶密碼、數據庫JDBC驅動類、數據庫dialect。用於對特定數據庫提供支持,其中包含了針對特定數據庫特性的實現,如Hibernate數據庫類型到特定數據庫數據類型的映射等。

    使用Hibernate必須首先提供這些基礎信息以完成初始化工做,爲後續操做作好準備。這些屬性在Hibernate配置文件hibernate.cfg.xml中加以設定,當調用:

Configuration config=new Configuration().configure();

時,Hibernate會自動在目錄下搜索hibernate.cfg.xml文件,並將其讀取到內存中做爲後續操做的基礎配置

2)SessionFactory接口

    SessionFactory負責建立Session實例,能夠經過Configuration實例構建SessionFactory。

Configuration config=new Configuration().configure();
SessionFactory sessionFactory=config.buildSessionFactory();

    Configuration實例config會根據當前的數據庫配置信息,構造SessionFacory實例並返回。SessionFactory一旦構造完畢,即被賦予特定的配置信息。就是說,以後config的任何變動將不會影響到已經建立的SessionFactory實例sessionFactory。若是須要使用基於變動後的config實例的SessionFactory,須要從config從新構建一個SessionFactory實例。若是須要訪問多個數據庫,針對每一個數據庫,應分別建立其對應的SessionFactory實例

    SessionFactory保存了對應當前數據庫配置的全部映射關係,同時也負責維護當前的二級數據緩存和Statement Pool。因而可知,SessionFactory的建立過程很是複雜、代價高昂。這也意味着,在系統設計中充分考慮到SessionFactory的重用策略。因爲SessionFactory採用了線程安全的設計,可由多個線程併發調用。大多數狀況下,針對一個數據庫共享一個SessionFactory實例便可

3)Session接口

    Session是Hibernate持久化操做的基礎提供了衆多持久化方法,如save、update、delete等。經過這些方法,透明地完成對象的增長、刪除、修改、查找等操做。

    同時,值得注意的是,Hibernate Session的設計是非線程安全的,即一個Session實例同時只可由一個線程使用。同一個Session實例的多線程併發調用將致使難以預知的錯誤

    Session實例由SessionFactory構建:

Configuration config=new Configuration().configure();
SessionFactory sessionFactory=config.buldSessionFactory();
Session session=sessionFactory.openSession();

4)Transaction接口

    Transaction是Hibernate中進行事務操做的接口,Transaction 接口是對實際事務實現的一個抽象,這些實現包括JDBC的事務、JTA 中的UserTransaction,甚至能夠是CORBA 事務。之因此這樣設計是可讓開發者可以使用一個統一的操做界面,使得本身的項目能夠在不一樣的環境和容器之間方便地移值。事務對象經過Session建立。例如如下語句:

Transaction ts=session.beginTransaction();

5)Query接口

    在Hibernate 2.x中,find()方法用於執行HQL語句Hibernate 3.x廢除了find()方法,取而代之的是Query接口,它們都用於執行HQL語句。Query和HQL是分不開的。

Query query=session.createQuery(「from Kcb where kch=198」);

上面是直接給出查詢條件的值,也能夠是設參數,例如如下語句:

Query query=session.createQuery("from Kcb where kch=?");

就要在後面設置其值:

Query.setString(0, "要設置的值");

上面的方法是經過「?」來設置參數,還能夠用「:」後跟變量的方法來設置參數,如上例能夠改成:

Query query=session.createQuery("from Kcb where kch=:kchValue");
Query.setString("kchValue","要設置的課程號值");

    因爲上例中kch爲String類型,因此要用setString(),若是是int型,就要用setInt()。通用的方法是setParameter()方法,不論是什麼類型的參數均可以。其使用方法是相同的,例如:

Query.setParameter(0, "要設置的值");

Query還有一個list()方法,用於取得一個List集合的示例,此示例中包括多是一個Object集合也多是Object數組集合。例如:

Query query=session.createQuery("from Kcb where kch=198");
List list=query.list();

4.HQL查詢

    Hibernate Query Language。語法與SQL很像,但HQL是一種面向對象的查詢語言SQL的操做對象是數據表和列等數據對象,而HQL的操做對象是類、實例、屬性等。HQL的查詢依賴於Query類每一個Query實例對應一個查詢對象

Query query=session.createQuery(「from Kcb where kch=198」);

    HQL經常使用的幾種查詢方式:

1)基本查詢

    基本查詢是HQL中最簡單的一種查詢方式。下面以課程信息爲例說明其幾種查詢狀況。

    (1)查詢全部課程信息

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
Query query=session.createQuery("from Kcb");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

    (2)查詢某門課程信息

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查詢一門學時最長的課程
Query query=session.createQuery("from Kcb order by xs desc");
query.setMaxResults(1);                        // 設置最大檢索數目爲1
// 裝載單個對象
Kcb kc=(Kcb)query.uniqueResult();
ts.commit();
HibernateSessionFactory.closeSession();

(3)查詢知足條件的課程信息

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查詢課程號爲001的課程信息
Query query=session.createQuery("from Kcb where kch=001");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

2)條件查詢

    查詢的條件有幾種狀況,下面舉例說明。

(1)按指定參數查詢

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查詢課程名爲計算機基礎的課程信息
Query query=session.createQuery("from Kcb where kcm=?");
query.setParameter(0, "計算機基礎");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

(2)使用範圍運算查詢

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查詢這樣的課程信息,課程名爲計算機基礎或數據結構,且學時在40~60之間
Query query=session.createQuery("from Kcb where (xs between 40 and 60) and kcm in('計算機基礎','數據結構')");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

 

(3)使用比較運算符查詢

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查詢學時大於51且課程名不爲空的課程信息
Query query=session.createQuery("from Kcb where xs>51 and kcm is not null");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


(4)使用字符串匹配運算查詢

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查詢課程號中包含「001」字符串且課程名前面三個字爲計算機的全部課程信息
Query query=session.createQuery("from Kcb where kch like '%001%' and kcm like '計算機%'");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

3)分頁查詢

    爲了知足分頁查詢的須要,Hibernate的Query實例提供了兩個有用的方法:setFirstResult(int firstResult)setMaxResults(int maxResult)。其中setFirstResult(int firstResult)方法用於指定從哪個對象開始查詢(序號從0開始),默認爲第1個對象,也就是序號0。SetMaxResults(int maxResult)方法用於指定一次最多查詢出的對象的數目默認爲全部對象。以下面的代碼片斷:

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
Query query=session.createQuery("from Kcb");
int pageNow=1;                                // 想要顯示第幾頁
int pageSize=5;                                // 每頁顯示的條數
query.setFirstResult((pageNow-1)*pageSize);                // 指定從哪個對象開始查詢
query.setMaxResults(pageSize);                        // 指定最大的對象數目
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


附:目錄《JavaEE基礎實用教程》筆記說明

相關文章
相關標籤/搜索