官术网_书友最值得收藏!

1.4 Hibernate增刪改查

接下來以求職者Seeker為例,示范如何使用Hibernate完成單表的增刪改查。還記得ORM的概念嗎?實體關系映射!要使用ORM,必然要有一個實體類,還有數據表(在執行Hibernate增刪改查前,須在Oracle數據庫中建立如1.2.3小節所示的表),還需要將二者映射起來(具體體現為一個XML實體類映射文件),最后使用API來完成持久化操作。所以,本節案例的大體思路是:

(1)創建實體類。

(2)創建和配置映射文件。

(3)使用API進行持久化操作。

1.4.1 創建實體類

實體類(也稱持久化類)是一個帶有一些屬性的JavaBean類,實體類對屬性的存取方法使用了標準JavaBean命名約定,同時把類屬性的訪問級別設成私有的。這是推薦的設計,也是面向對象編程的基礎。為了通過反射機制來實例化類的對象,需要提供一個無參的構造器,所有的實體類都要求有無參的構造器,因為Hibernate需要使用Java反射機制來創建對象。最后要為實體類實現java.io.Serializable接口,以便Hibernate能更好地緩存實體對象。

創建/5iJob/src/org/ijob/bean/Seeker.java,代碼如下:

        package org.ijob.bean;
        import java.SQL.Blob;
        import java.SQL.Date;
        import java.util.Set;
        /**
        * 求職者基本信息
        *
        */
        public class Seeker {
            private String id;
            private String email;                      //郵件
            private String password;                   //密碼
            private String name;                       //真實姓名
            private String sex="1";                    //性別
            private Date birth;                        //出生日期
            private int workYear;                      //工作年限
            private String idType;                     //證件類型
            private String idNum;
            private String residence;                  //居住地
            private double annualSalary;               //年薪
            private String phoneNum="";                //電話號碼
            private String homePhoneNum="";            //家庭電話號碼
            private String compPhoneNum="";            //公司電話號碼
            private String jobStatus="1";              //工作狀態
            private String householdRegister;          //戶籍
            private String keyWord;                    //關鍵字
            private int bodyHigh;                      //身高
            private String currency="1";               //幣種
            private String maritalStatus="1";          //婚姻狀況
            private String postcode;                   //郵編
            private String address;                    //地址
            private String qq;                         //QQ號
            private String blog;                       //個人博客地址
            private Blob face;                         //頭像
            //此處省略getter&setter方法
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                Seeker other = (Seeker) obj;
                if (id == null) {
                    if (other.id != null)
                        return false;
                } else if (!id.equals(other.id))
                    return false;
                return true;
            }
        }

1.4.2 創建和配置映射文件

● 創建映射文件

在介紹Hibernate主配置文件hibernate.cfg.xml文件時,提到了該配置文件最后一部分是配置實體映射文件的路徑。通過實體映射文件,Hibernate知道怎樣去加載和存儲實體類的對象,知道應該訪問數據庫里的哪個表及應該使用表里的哪些字段。

下面是一個實體類映射文件的基本結構:

        <?xml version="1.0"?>
        <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        <hibernate-mapping>
        ...
        </hibernate-mapping>

以這個結構為模板,創建/5iJob/src/org/ijob/bean/Seeker.hbm.xml,在其中輸入實體類與表的映射信息。

        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        <hibernate-mapping>
            <class name="org.ijob.bean.Seeker" table="ijob_seeker">
                <!-- 主鍵映射 -->
                <id name="id" type="string">
                    <column name="id" length="32"></column>
                    <generator class="uuid" />
                </id>
                <!-- 屬性映射 -->
                <property name="email" type="string">
                    <column name="email" length="100"></column>
                </property>
                <property name="password" type="string">
                    <column name="password" length="20"></column>
                </property>
                <property name="name" type="string">
                    <column name="name" length="10"></column>
                </property>
                <!-- 此處省略系列屬性映射 -->
            </class>
        </hibernate-mapping>

在實體類映射文件中,被映射的類必須定義對應數據庫表的主鍵字段的屬性。映射文件的<id>元素定義了該屬性到數據庫表主鍵字段的映射。

        <id name="propertyName"type="typename">           1
            <column="column_name"></column>              2
            <generator class="generatorClass"/>           3
        </id>

代碼解析:

1.name:屬性名,type:Hibernate類型。

2.column:主鍵字段名,默認為屬性名。

3.主鍵生成器generator是可選的,它用于指定實體對象的標識符(在表中稱之為主鍵)生成策略,下面是一些常見的主鍵生成策略。

increment:類似于數據表中的自增列,往數據庫插入一個新的實體對象時,其標識符(主鍵)為上一次插入對象的標識符加1。

identity:每次新增對象時,調用數據庫本身的identity生成器產生標識符。

sequence:每次新增對象時,調用數據庫的sequence對象產生標識符。

配置舉例:

        <generator class="sequence" >
            <param name="sequence">sequence_name</param><!--sequence對象的名字 -->
        </generator>

這樣配置之后,每次往數據庫中插入新對象,都調用數據庫的sequence_name所指定的sequence對象來產生標識符。

uuid:每次新增對象時,用一個128bit的UUID算法生成長度為32的字符串類型的標識符,這是本項目實際采用的主鍵生成方式。

assigned:不提供主鍵自動生成支持,而是讓應用程序在插入新對象之前手動為對象分配一個標識符,這是沒有<generator>元素時的默認生成策略。

● 在主配置文件中添加實體映射文件路徑

將映射文件的路徑信息添加到hibernate.cfg.xml中,代碼如下:

        <mapping resource="org/ijob/bean/Seeker.hbm.xml" />

1.4.3 數據庫操作

使用Hibernate操作數據庫大體上可劃分為7個步驟,如圖1.6所示。接下來遵循這7個步驟,完成針對單表的增刪改查操作。

圖1.6 Hibernate操作數據庫的7個步驟

● 保存求職者信息

在HibernateTest類中新建方法(方便測試):

        public static void save(){
            //創建Configuration
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(cfg.getProperties()).buildServiceRegistry();
            //創建SessionFactory
            SessionFactory factory = cfg.buildSessionFactory(serviceRegistry);
            //獲取Session
            Session session = factory.openSession();
            Transaction tx = session.getTransaction();
            try {
                //開始一個事務
                tx.begin();
                Seeker seeker = new Seeker();
                seeker.setEmail("abc@163.com");
                seeker.setPassword("abc");
                //保存seeker對象
                session.save(seeker);
                //提交事務
                session.getTransaction().commit();
            } catch (Exception e) {
                tx.rollback();
                e.printStackTrace();
            } finally {
                //關閉Session
                session.close();
            }
        }

雖然Seeker類有很多屬性,但作為示范,本例只為該類兩個屬性賦值,其余屬性的賦值和這兩個屬性的賦值類似。特別需要注意,不可以為seeker對象的id屬性賦值,因為這里使用uuid主鍵生成策略,Hibernate框架將自動使用uuid算法為seeker對象生成id屬性。Session的save()方法是一個常用方法,用于將實體對象持久化到數據庫中。

圖1.7顯示了數據庫中新增一行記錄的結果。

圖1.7 新增數據結果

復制這個id值(實際得到的id值和本例中的id值不同),在下面的代碼中將會用到。

● 根據主鍵查詢求職者信息

具體代碼如下:

        public static void get(){
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(cfg.getProperties()).buildServiceRegistry();
            SessionFactory factory = cfg.buildSessionFactory(serviceRegistry);
            Session session = factory.openSession();
            Seeker seeker=(Seeker)session.get(Seeker.class,"替換為id");
            System.out.println(seeker.getEmail()+","+seeker.getPassword());
            session.close();
        }

如代碼所示,僅調用Session對象的get()方法便能從數據庫中獲取一行數據并轉換為一個實體對象。Session提供了兩種通過主鍵值加載數據的方法,即get()方法和load()方法。這兩個方法均可以根據指定的實體類和id從數據庫讀取記錄,并返回與之對應的實體對象。兩者區別在于:

(1)如果未能發現符合條件的記錄,get()方法返回null,而load()方法會拋出一個ObjectNotFoundException。

(2)load()方法可返回實體的代理類實例,而get()方法直接返回實體類對象。Load()方法可以充分利用Session級緩存(也稱一級緩存)和SessionFactory級緩存(也稱二級緩存,可以被來自同一個SessionFactory的所有Session共享)中的現有緩存數據,而get()方法則僅僅在Session級緩存中進行數據查找,如沒有發現對應數據,將越過二級緩存,直接調用SQL完成數據讀取。因此load()方法可充分地利用二級緩存來提高數據的使用效率,對那些經常讀取而較少修改的數據可設置二級緩存,并通過load()方法進行讀取,能提高數據加載的效率。load()方法使用如下:

        Seeker seeker=(Seeker)session.load(Seeker.class,"替換為id");

(3)get()和load()方法還有一些其他重要區別,將在隨后的課程中進行介紹。

● 更新求職者信息

具體代碼如下:

        public static void update(){
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(cfg.getProperties()).buildServiceRegistry();
            SessionFactory factory = cfg.buildSessionFactory(serviceRegistry);
            Session session = factory.openSession();
            Seeker seeker=(Seeker)session.get(Seeker.class,"替換為id");
            Transaction tx = session.getTransaction();
            try {
                tx.begin();
                seeker.setPassword("alex");
                //更新seeker對象
                session.update(seeker);
                session.getTransaction().commit();
            } catch (Exception e) {
                tx.rollback();
                e.printStackTrace();
            } finally {
                session.close();
            }
        }

如代碼所示,修改一個對象的步驟很簡單:先加載實體對象,像對象普通操作那樣調用setter方法更改其屬性值,最后調用Session的update()方法將新的狀態持久化到數據庫中。

● 刪除求職者

具體代碼如下:

        public static void delete(){
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                    .applySettings(cfg.getProperties()).buildServiceRegistry();
            SessionFactory factory = cfg.buildSessionFactory(serviceRegistry);
            Session session = factory.openSession();
            Seeker seeker=(Seeker)session.get(Seeker.class,"替換為id");
            Transaction tx = session.getTransaction();
            try {
                tx.begin();
                session.delete(seeker);
                session.getTransaction().commit();
            } catch (Exception e) {
                tx.rollback();
                e.printStackTrace();
            } finally {
                session.close();
            }
        }

如代碼所示,刪除一個實體對象也很簡單:先加載實體對象,然后調用Session的delete()方法就能將該實體對象刪除(實際上就是刪除了數據表中的一行數據)。

點評

本節示例了如何通過Hibernate API對Seeker類對象執行增刪改查操作,從而完成數據庫操作。這些操作的前提是配置了數據庫連接信息和實體類與數據表的映射關系。進行每一個操作都套用了圖1.6所示的7個步驟。這些操作分別使用了Session接口的save()、get()、load()、update()、delete()方法,這些方法都是持久化操作的核心方法,讀者有必要熟練掌握。

主站蜘蛛池模板: 闸北区| 宿州市| 石城县| 湛江市| 赤水市| 庆云县| 易门县| 屯门区| 景泰县| 来安县| 长治县| 波密县| 九台市| 建德市| 西乡县| 喀喇沁旗| 洮南市| 色达县| 孟津县| 青河县| 上林县| 黑河市| 万载县| 嘉荫县| 高碑店市| 西昌市| 蒙自县| 阿坝县| 柳州市| 濮阳县| 彭泽县| 富平县| 津市市| 徐州市| 吐鲁番市| 松原市| 万全县| 锦屏县| 十堰市| 宝坻区| 临夏县|