持久化對象的狀態
:
1、 瞬時對象(Transient Object):使用new操作符初始化的對象不是立刻就持久的。它們的狀態是瞬時的,也就是說它們沒有任何跟數據庫表相關聯的行為,只要應用不再引用這些對象(不再被任何其它對象所引用),它們的狀態將會丟失,並由垃圾回收機制回收
2、 持久化對象(Persistent Object):持久實例是任何具有數據庫標識的實例,它有持久化管理器Session統一管理,持久實例是在事務中進行操作的----它們的狀態在事務結束時同數據庫進行同步。當事務提交時,通過執行SQL的INSERT、UPDATE和DELETE語句把內存中的狀態同步到數據庫中。
3、 離線對象(Detached Object):Session關閉之后,持久化對象就變為離線對象。離線表示這個對象不能再與數據庫保持同步,它們不再受hibernate管理。
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),然后根據映射文件生成數據庫表。數據庫對我來說是透明的,我們只操作對象不用關心數據庫。