hibernate--持久對象的生命周期介紹


持久化對象的狀態

1、 瞬時對象(Transient Object):使用new操作符初始化的對象不是立刻就持久的。它們的狀態是瞬時的,也就是說它們沒有任何跟數據庫表相關聯的行為,只要應用不再引用這些對象(不再被任何其它對象所引用),它們的狀態將會丟失,並由垃圾回收機制回收

2、 持久化對象(Persistent Object):持久實例是任何具有數據庫標識的實例,它有持久化管理器Session統一管理,持久實例是在事務中進行操作的----它們的狀態在事務結束時同數據庫進行同步。當事務提交時,通過執行SQL的INSERT、UPDATE和DELETE語句把內存中的狀態同步到數據庫中。

3、 離線對象(Detached Object):Session關閉之后,持久化對象就變為離線對象。離線表示這個對象不能再與數據庫保持同步,它們不再受hibernate管理。

 

wps_clip_image-7196

Transient對象:隨時可能被垃圾回收器回收(在數據庫中沒有於之對應的記錄,應為是new初始化),而執行save()方法后,就變為Persistent對象(持久性對象),沒有納入session的管理

Persistent對象:在數據庫有存在的對應的記錄,納入session管理。在清理緩存(臟數據檢查)的時候,會和數據庫同步。

Detached對象:也可能被垃圾回收器回收掉(數據庫中存在對應的記錄,只是沒有任何對象引用它是指session引用),注引狀態經過Persistent狀態,沒有納入session的管理

測試代碼:

package h.one.test;

import h.one.bean.User;
import h.one.utils.HibernateUtil;

import java.util.Date;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

public class testSave1 {

    @Test
    public void testSave1() {
        Session session = null;
        Transaction tx = null;
        User user = null;

        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();

            // Transient狀態
            user = new User();
            user.setName("李四");
            user.setPassword("123");
            user.setCreateTime(new Date());
            user.setExpireTime(new Date());

            /*
             * persistent狀態 persistent狀態的對象,當屬性發生改變的時候,hibernate會自動和數據庫同步
             */
            session.save(user);

            user.setName("王五");
            // 實際上user.setName("王五")此時已經發出一條update指令了。
            // 也可以顯示的調用update指定
            // session.update(user);

            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            HibernateUtil.closeSession(session);
        }

        /*
         * 從此處開始session已經在上面關閉,這時user對象狀態就變為detached狀態,
         * 所有user對象已經不被session管理,但數據庫中確實存在與至對應的記錄(王五)。
         */
        // detached狀態
        user.setName("張三");

        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            /*
             * 此時session又對user對象進行管理 當session發出update指定后,進行更新數據為(張三。)
             */
            session.update(user);

            // update后user對象狀態又變為persistent狀態
            session.getTransaction().commit();
            /*
             * 此時session提交事務,發出update語句 Hibernate: update User set name=?,
             * password=?, createTime=?, expireTime=? where id=?
             */
        } catch (HibernateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            session.getTransaction().rollback();
        } finally {
            HibernateUtil.closeSession(session);
        }
    }
}

Hibernate加載數據:

兩種:get()、load()

一、 Session.get(Class clazz,  Serializable id)方法

* clazz:需要加載對象的類,例如:User.class

* id:查詢條件(實現了序列化接口的對象):

例"4028802c46d255740146d25576320000"字符串已經實現了序列化接口。

返回值: 此方法返回類型為Object,也就是對象,然后我們再強行轉換為需要加載的對象就可以了。

如果數據不存在,則返回null;

注:執行此方法時立即發出查詢SQL語句。加載User對象

加載數據庫中存在的數據,代碼如下

@Test
    public void testLoad() {
        Session session = null;
        Transaction tx = null;

        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();

            /*
             * Object org.hibernate.Session.get(Class arg0, Serializable arg1)
             * throws HibernateException arg0:需要加載對象的類,例如:User.class
             * arg1:查詢條件(實現了序列化接口的對象
             * ):例"4028818a245fdd0301245fdd06380001"字符串已經實現了序列化接口。
             * 此方法返回類型為Object,也就是對象,然后我們再強行轉換為需要加載的對象就可以了。 如果數據不存在,則返回null
             * 執行此方法時立即發出查詢SQL語句。加載User對象。
             */
            User user = (User) session.get(User.class,"4028802c46d255740146d25576320000");

            // 數據加載完后的狀態為persistent狀態。數據將與數據庫同步。
            System.out.println("user.name=" + user.getName());

            // 因為此的user為persistent狀態,所以數據庫進行同步為龍哥。
            user.setName("龍哥");
            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        } finally {
            if (session != null) {
                if (session.isOpen()) {
                    session.close();
                }
            }
        }
    }

一、 Object Session.load(Class clazz, Serializable id) throws HibernateException

* clazz:需要加載對象的類,例如:User.class

* id:查詢條件(實現了序列化接口的對象):例"4028802c46d255740146d25576320000"字符串已經實現了序列化接口。

* 此方法返回類型為Object,但返回的是代理對象。

* 執行此方法時不會立即發出查詢SQL語句。只有在使用對象時,它才發出查詢SQL語句,加載對象。

* 因為load方法實現了lazy(稱為延遲加載、賴加載)

* 延遲加載:只有真正使用這個對象的時候,才加載(才發出SQL語句)

* hibernate延遲加載實現原理是代理方式。

* 采用load()方法加載數據,如果數據庫中沒有相應的記錄,則會拋出異常對象不找到(org.hibernate.ObjectNotFoundException)

@Test
    public void testLoad() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();

            User user = (User) session.load(User.class,
                    "4028802c46d255740146d25576320000");

            // 只有在使用對象時,它才發出查詢SQL語句,加載對象。
            System.out.println("user.name=" + user.getName());

            // 因為此的user為persistent狀態,所以數據庫進行同步為龍哥。
            user.setName("發哥");

            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        } finally {
            if (session != null) {
                if (session.isOpen()) {
                    session.close();
                }
            }
        }
    }

ibernate兩種加載數據方式的區別:

get()方法默認不支持lazy(延遲加載)功能,而load支持延遲加載

get()方法在查詢不到數據時,返回null,而load因為支持延遲加載,只有在使用對象時才加載,所以如果數據庫中不在數據load會拋出異常(org.hibernate.ObjectNotFoundException)。

get()和load()只根據主鍵查詢,不能根據其它字段查詢,如果想根據非主鍵查詢,可以使用HQL

hibernate更新數據:

建立使用hibernate進行更新數據時,先加載數據,然后再修改后更新。

否則一些字段可以會被null替換。

@Test
    public void testDelete() {
        Session session = null;
        Transaction tx = null;

        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();

            User user = (User) session.load(User.class,
                    "4028802c46d255740146d25576320000");
            session.delete(user);

            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        } finally {
            if (session != null) {
                if (session.isOpen()) {
                    session.close();
                }
            }
        }
        // transistent狀態(數據庫中沒有配區的數據記錄。)
    }

query接口初步

Query session.createQuery(String hql)方法;

* hibernate的session.createQuery()方法是使用HQL(hibernate的查詢語句)語句查詢對象的。

* hql:是查詢對象的,例如:"from User",其中from不區分大小寫,而User是區分大小寫,因為它是對象。是User類

* 返回Query對象。

* 執行這條語句后,Hibernate會根據配置文件中所配置的數據庫適配器自動生成相應數據庫的SQL語句。如:

ibernate: select user0_.id as id0_, user0_.name as name0_, user0_.password as password0_, 
user0_.createTime as createTime0_, user0_.expireTime as expireTime0_ from User user0_

Query的分頁查詢:

@Test
    public void testQuery1() {
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            Query query = session.createQuery("from User");
            // 分頁查詢
            query.setFirstResult(0);// 從哪一條記錄開始查詢,是從0開始計算
            query.setMaxResults(2);// 分頁每頁顯示多少條記錄。
            /*
             * Query對象中有一個list()方式,將所有查詢來的對象自動生成list對象返回。
             */
            List userList = query.list();
            // 然后我們就可以顯示數據了。
            for (Iterator iter = userList.iterator(); iter.hasNext();) {
                User user = (User) iter.next();
                System.out.print(user.getId() + "   ");
                System.out.println(user.getName());
            }
            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        } finally {
            HibernateUtil.closeSession(session);
        }
    }

總結:

Hibernate是一個O/R映射框架(也稱為ORM)

從ORM詞來看,O---Object(對象模型);R--- Relational(關聯模型),可以做對象和關聯的一種映射,當然這只是部分功能,一個完善ORM框架應該具有更多的功能:如HQL相關的查詢語句、提供緩存機制(一級緩存、二級緩存)。

Java開發數據庫時,使用JDBC,但是需要編寫大量相同的代碼,這樣不便提高生產效率,而hibernate可以讓你不能編寫大量的相同的代碼。從而提高生產效率。另一方面,hibernate可以讓我們更面對象化開發,還有一個移植性hibernate只需要更改配置文件(數據庫適配器)的選項,就可以非常方便的移植到不同的數據庫,而不需要重新編寫不同數據庫廠家所對應的JDBC、SQL語句了。還有hibernate可以解決阻抗不匹配(Java類中有繼承關系,而關系型數據庫中沒有這個功能(目前數據庫還不是面向對象,都是關系型數據庫)),使用hibernate框架,侵入性比較好(因此hibernate稱為輕量級框架)

O/R映射框架和使用環境:在程序中添加→修改→保存;查詢可以批量,但是修改不可為批量性;程序中有大量的數據只讀,這樣就可以一次性讀取到緩存中;對象間存在自然的關系;不需要數據庫SQL特定的語句優化。

O/R映射框架不適合環境:聚集性操作:批量性添加、修改。批量的統計查詢。

Configuration對象:讀取hibernate配置文件(hibernate.cfg.xml或hiberante.properties)的. new Configuration()默認是讀取hibernate.properties, 所以使用new Configuration().configure();來讀取hibernate.cfg.xml配置文件

SessionFactory:是一個重量級對象,它的創建是耗時的。因為它對應一個數據庫里所有配置,包括一些緩存機制都由SessionFactory來維護,它與二級緩存是綁定的。通常只創建一次,但它是線程安全的。

Session:是非線程安全的,它是通過SessionFactory來創建的。不要多個線程同時訪問同一個Session,否則會出現一些未知問題。通常是一個請求對應一個Session,請求完成要關閉Session

Transaction:hibernate默認不是自動開啟事務的,所以要手動開啟事務、手動提交事務、手動回滾事務、手動關閉事務。當然可以通過配置文件配置成自動。一般使用手動。

Hibernate正常的開發思路:考慮對象模型這一塊,把對象模型建立起來,把對象圖建立起來,對象之間的關系建立起來、然后再編寫映射文件(hbm),然后根據映射文件生成數據庫表。數據庫對我來說是透明的,我們只操作對象不用關心數據庫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM