10 10Hibernate之對象狀態

Hibernate的開發理論來源就是EJB 2.x Entity Bean(實體Bean),在實體Bean裏面有一個特點,每當調用了對象中的setter()方法,那麼就可以自動的進行數據更新。所以Hibernate本身也具備此類操作,那麼在Hibernate之中爲了更好的理解POJO類的對象所處的狀態,專門提供有三種狀態:
(1)瞬時態(Transient):對象保存在內存之中,並沒有在數據庫之中進行存儲,也就是說如果對象一直沒有存儲,那麼就有可能被GC回收,回收之後就像不存在一樣;
(2)持久態(Persistent):將內存中的對象保存在數據庫之中,或者某一個對象通過數據庫讀取,此時Session如果沒有關閉,那麼就是持久態,持久態的最大特徵就是屬性的變化將引起數據庫的變化;
(3)遊離態(Detached):如果Session關閉了,那麼已經讀取出來的數據就變爲遊離態,這個時候對象保存在內存之中,如果長時間不使用將被GC回收,與瞬時態最大區別只有一點:此時數據庫之中有對應數據。
範例:瞬時態——此時沒保存

package org.lks.test;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.lks.pojo.Member;

public class TestMemberDemo {
	public static void main(String[] args) throws ParseException {
		Member member = new Member();
		member.setMid("3181301102");	
		member.setMname("hhy");
		member.setMage(20);
		member.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1999-08-21"));
		member.setMsalary(10000.0);
		member.setMnote("big fool!");
	}
}

整個的代碼操作過程之中,Member對象只存在於內存之中,並沒有利用Session進行保存。
範例:由瞬時態變爲持久態——只需要使用save()方法保存

package org.lks.test;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;

public class TestMemberDemo {
	public static void main(String[] args) throws ParseException {
		Member member = new Member();
		member.setMid("31813011021");	
		member.setMname("hhy");
		member.setMage(20);
		member.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1999-08-21"));
		member.setMsalary(10000.0);
		member.setMnote("big fool!");
		//進行數據庫保存,所以由瞬時態變爲了持久態
		System.out.println(HibernateSessionFactory.getSession().save(member));
		HibernateSessionFactory.getSession().beginTransaction().commit();
	}
}

31813011021
Hibernate: 
    insert 
    into
        hedb.member
        (mage, mbirthday, mname, mnote, msalary, mid) 
    values
        (?, ?, ?, ?, ?, ?)

如果某一個對象處於持久態的狀態下,只需要調用setter方法就可以更新了。
範例:觀察持久態的操作形式

package org.lks.test;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;

public class TestMemberDemo {
	public static void main(String[] args) throws ParseException {
		Member member = new Member();
		member.setMid("31813011022");	
		member.setMname("hhy");
		member.setMage(20);
		member.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1999-08-21"));
		member.setMsalary(10000.0);
		member.setMnote("big fool!");
		//進行數據庫保存,所以由瞬時態變爲了持久態
		System.out.println(HibernateSessionFactory.getSession().save(member));
		HibernateSessionFactory.getSession().beginTransaction().commit();
		//此時Session並沒有關閉
		member.setMsalary(100.0);
		HibernateSessionFactory.getSession().beginTransaction().commit();
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

31813011022
Hibernate: 
    insert  → HibernateSessionFactory.getSession().save(member)
    into
        hedb.member
        (mage, mbirthday, mname, mnote, msalary, mid) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    update   →  member.setMsalary(100.0);
        hedb.member 
    set
        mage=?,
        mbirthday=?,
        mname=?,
        mnote=?,
        msalary=? 
    where
        mid=?

因爲現在Session沒有關閉,對象屬於持久態的狀態,所以可以直接利用setter更新數據。

實際上在Session裏面存在有get()與load()兩個操作方法,這兩個操作方法都是根據ID進行數據查詢,如果說現在使用ID查詢的話,那麼對象也處於持久態(前提:不關閉Session)。
範例:觀察持久態

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;

public class TestMemberGet {
	public static void main(String[] args) {
		//在Session沒有關閉之前處於持久態
		Member vo = (Member) HibernateSessionFactory.getSession().get(Member.class, "3171301102");
		//此時Session現在並沒有關閉,對象爲持久態
		vo.setMsalary(10000.0);
		vo.setMnote("super big fool!");
		HibernateSessionFactory.getSession().beginTransaction().commit();
	}
}

Hibernate: 
    select  →   HibernateSessionFactory.getSession().get(Member.class, "3171301102");
        member0_.mid as mid1_0_0_,
        member0_.mage as mage2_0_0_,
        member0_.mbirthday as mbirthda3_0_0_,
        member0_.mname as mname4_0_0_,
        member0_.mnote as mnote5_0_0_,
        member0_.msalary as msalary6_0_0_ 
    from
        hedb.member member0_ 
    where
        member0_.mid=?
Hibernate: 
    update  →  vo.setMsalary(10000.0);  vo.setMnote("super big fool!");
        hedb.member 
    set
        mage=?,
        mbirthday=?,
        mname=?,
        mnote=?,
        msalary=? 
    where
        mid=?

如果在進行一些登錄操作的時候,可能會更新某一個用戶最後一次登錄日期,那麼就可以利用持久態實現這類的操作。
範例:遊離態

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;

public class TestMemberDetached {
	public static void main(String[] args) {
		//在Session沒有關閉之前處於持久態
		Member vo = (Member) HibernateSessionFactory.getSession().get(Member.class, "3171301102");
		//此時Session關閉了,關閉之後變爲遊離態
		HibernateSessionFactory.closeSession();
		//此時Session現在並沒有關閉,對象爲持久態
		vo.setMsalary(10000.0);
		vo.setMnote("super big fool!");
		HibernateSessionFactory.getSession().beginTransaction().commit();
	}
}

Hibernate: 
    select  →   HibernateSessionFactory.getSession().get(Member.class, "3171301102");
        member0_.mid as mid1_0_0_,
        member0_.mage as mage2_0_0_,
        member0_.mbirthday as mbirthda3_0_0_,
        member0_.mname as mname4_0_0_,
        member0_.mnote as mnote5_0_0_,
        member0_.msalary as msalary6_0_0_ 
    from
        hedb.member member0_ 
    where
        member0_.mid=?

因爲現在變爲了遊離態,所以所有數據的修改不會影響到數據庫中的實體數據。

口訣:
(1)瞬時態與遊離態無法更新數據;
(2)持久態可以更新,但是必須在Session關閉之前完成更新;
切換方法:
(1)瞬時態→持久態:save()方法、update()方法;
(2)持久態→遊離態:關閉Session;
(3)遊離態→瞬時態:delete()操作;

面試題:請解釋Hibernate對象的三種狀態?
(1)Hibernate對象數據分別有:瞬時態、持久態、遊離態;
(2)瞬時態指的是對象只在內存中保存,數據庫沒有對應數據;
(3)持久態指的是在對象保存或者取得之後不關閉Session的情況下,可以利用setter進行數據修改;
(4)遊離態指的是對象讀取完成或保存成功之後關閉了Session後的狀態,此時數據庫有對應數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章