深刻解析Java的Hibernate框架中的耐久對象。本站提示廣大學習愛好者:(深刻解析Java的Hibernate框架中的耐久對象)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻解析Java的Hibernate框架中的耐久對象正文
1、耐久對象性命周期
運用法式在應用Hibernate框架後,創立的耐久對象會閱歷一整套性命周期來完成數據庫的操作,個中重要的三個狀況分離是瞬態(Transient)、耐久化(Persistent)、脫管(detached)。這三種狀況的轉換是可以或許在運用法式中掌握的,以下圖:
為了能清晰的懂得這幾種狀況,這裡應用一個實例來檢查下這幾種狀況下對象的分歧,上面狀況內的代碼,詳細步調以下:
(1)創立Hibernate_session法式集,並添加像響應的jar包;
(2)設置裝備擺設Hibernate,添加響應的實體User類,及它的映照文件,並設置裝備擺設好響應的數據庫銜接;
User類文件的映照文件User.hbm.xml代碼:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2014-4-30 15:39:33 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.hibernate.User"> <id name="id"> <generator class="uuid"/> </id> <property name="name"/> <property name="password"/> <property name="createTime"/> <property name="expireTime"/> </class> </hibernate-mapping>
Hibernate數據庫銜接設置裝備擺設代碼:
<?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> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_session</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">ab12</property> <!-- dialect:方言,封裝的底層API,相似於Runtime,將數據庫轉換為設置裝備擺設中的響應的說話 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <mapping resource="com/hibernate/User.hbm.xml"/> </session-factory> </hibernate-configuration>
(3)添加靜態成員sessionfactory的公共類,用來創立一個SessionFactory及其Session對象;
package com.hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class session { private static SessionFactory factory; //聲明靜態部分變量SessionFactory,數據庫鏡像 static{ try{ //創立並獲得設置裝備擺設數據庫的設置裝備擺設文件,默許獲得hibernate.cfg.xml Configuration cfg=new Configuration().configure(); factory=cfg.buildSessionFactory(); //構建一個數據庫鏡像 }catch(Exception e){ e.printStackTrace(); //打印毛病信息 } } public static Session getSession(){ return factory.openSession(); //前往創立的session對象 } public static SessionFactory getSessionFactory(){ return factory; //前往響應的SessionFactory } //封閉session對象 public static void closeSession(Session session){ if(session != null){ if(session.isOpen()){ session.close(); } } } }
(4)添加一個Source Folder,並在該文件夾內添加稱號為com.hibernate的package包,並在包中添加一個稱號為SessionTest的類文件。
package com.hibernate; import java.util.Date; import junit.framework.TestCase; import org.hibernate.Session; import org.hibernate.Transaction; public class SessionTest extends TestCase { }
2、狀況轉化辦法
1、對象直接進入Persistent狀況
1.1 get辦法
從數據庫中獲得一行信息,並將該信息同步到創立的對象中,該辦法前往一個Object對象,假如沒有查詢到內容則前往null。上面的實例經由過程采取Session的get辦法來獲得一個對象,並將對象轉換為實例。
public void testGet1(){ Session session=null; Transaction tx = null; try{ session=HibernateUtils.getSession(); //開啟事務 tx= session.beginTransaction(); //get加載下去的對象為耐久對象 //履行get會立時收回查詢語句,假如不存在會前往null User user=(User)session.get(User.class,"ff80808145bc28cc0145bc28ce020002"); System.out.println(user.getName()); //persistent狀況 //persistent狀況的對象,當對象的屬性產生轉變的時刻 //Hibernate在清算緩存(髒數據檢討)的時刻,會和數據庫同步 user.setName("趙柳"); session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); if(tx != null){ tx.rollback(); } }finally{ HibernateUtils.closeSession(session); } }
設置斷點,獲得User對象。
獲得到了該對象,經由過程強迫轉換後獲得了一個user對象。法式中添加了setName辦法,也就是說會更新數據庫中的稱號,履行完成後檢討數據庫,以下圖更新成果。
1.2 load辦法
功效相似於get辦法,也是從數據庫中獲得數據並同步到對象中,該辦法支撐lazy是一種懶漢操作,它前往的是一個耐久化的Object對象或許一個署理,所以須要停止轉化。
public void testLoad1(){ Session session=null; try{ session=HibernateUtils.getSession(); //不會立時查詢語句,由於load支撐lazy(延遲加載/懶加載) //甚麼教lazy?只要真正應用這個對象的時刻,再創立,關於Hibernate來講 //才真正收回查詢語句,重要為了進步機能,lazy是Hibernate中異常主要的特征 //Hibernate的lazy是若何完成的?采取署理對象完成,署理對象重要采取的是CGLIB庫生成的 //而不是JDK的靜態署理,由於JDK的靜態署理只能對完成了托言的類生成署理,CGLIB可以對類生成 //署理,它采取的是繼續方法 User user=(User)session.load(User.class,"8a1b653745bcc7b50145bcc7b7140001"); System.out.println(user.getName()); //persistent狀況 //persistent狀況的對象,當對象的屬性產生轉變的時刻 //Hibernate在清算緩存(髒數據檢討)的時刻,會和數據庫同步 user.setName("zhaoliu"); session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); }finally{ HibernateUtils.closeSession(session); } }
查詢獲得該User對象以下圖:
剖析上圖,獲得的User對象其實不完全,或許說並沒有罕見一個User對象,更是一種署理,它應用了CGLIB來預加載對象,只要在應用該對象時才真正創立。
1.3 Get Vs load
get和load辦法很主要,在面試Hibernate時常常會考到,上面比較下二者。
雷同點:
(1)功效雷同,將關系數據轉化為對象;
(2)應用辦法雷同,異樣須要制訂兩個參數
分歧點:
(1)load辦法支撐lazy操作,預加載對象,在應用時才創立,get是直接將關系數據轉化為對象;
(2)load加載對象假如不存在會拋出objectNotFoundException異常,get假如沒有獲得數據會前往null。
2、手動結構detached對象
想要獲得對象還有別的一種辦法,它差別於get與load辦法,是一種手動獲得的辦法,起首罕見一個對象,然後經由過程制訂id的方法獲得該對象的數據,辦法以下:
public void testUer(){ Session session=null; try{ session=HibernateUtils.getSession(); session.beginTransaction(); //手動結構detached對象 User user=new User(); user.setId("8a1b653745bcc7b50145bcc7b7140001"); //persistent狀況 //persistent狀況的對象,當對象的屬性產生轉變的時刻 //Hibernate在清算緩存(髒數據檢討)的時刻,會和數據庫同步 session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); }finally{ HibernateUtils.closeSession(session); } }
檢查獲得的成果圖:
剖析成果圖,代碼中應用了setId辦法為該對象制訂了id號,在制訂id號後就可以夠對該對象停止操作,在事務提交後同步到數據庫中,采取了手動指定,手動指定了對象的信息。
2.1 Delete辦法
刪除數據庫中指定的對象,在刪除前必需將對象轉化到Persistent狀況,可使用get、load或許手動的辦法指定對象,應用辦法以下代碼:
session=HibernateUtils.getSession(); session.beginTransaction(); User user=(User)session.load(User.class,"8a1b653745bcc6d50145bcc6d67a0001"); //建議采取此種方法刪除,先加載再刪除 session.delete(user);
2.2 Update
更新數據,該辦法會修正數據庫中的數據。在應用的時刻會湧現量中情形,更新數據庫某個字段值或許更新數據庫的整行值
2.2.1 更新某個字段值
假如只想要更新某個字段的值,在update前,須要應用load或許get辦法使對象轉化為persistent狀況代碼以下:
//獲得session對象 session=HibernateUtils.getSession(); //開啟事務 session.beginTransaction(); //或許可使用別的的辦法開啟 //session.getTransaction().begin(); //加載獲得User對象 //辦法一:應用load辦法 //User user=(User)session.load(User.class, "8a1b653745bcc7b50145bcc7b7140001"); //辦法二:手動獲得 User user=new User(); user.setId("8a1b653745bcc7b50145bcc7b7140001"); //更新姓名 user.setName("zhangsan"); session.update(user); session.getTransaction().commit();
2.2.2 更新整行
想要更新整行的數據,可以采取手動將狀況轉換到detached狀況,手動指定對象的id值,代碼以下:
//獲得session對象 session=HibernateUtils.getSession(); //開啟事務 session.beginTransaction(); //或許可使用別的的辦法開啟 //session.getTransaction().begin(); //手動獲得 User user=new User(); user.setId("8a1b653745bcc7b50145bcc7b7140001"); //更新姓名 user.setName("zhangsan"); session.update(user); session.getTransaction().commit();
檢查更新成果:
剖析更新成果,它其實更新了數據庫的整行數據,這類更新操作有太多的不肯定身分,不建議應用。
2.3 save辦法
拔出數據。在履行save辦法時會挪用數據庫的insert語句,向數據庫中添加新的一行。save後的對象會轉化為耐久態,在此狀況下的對象可以或許再次更新對象,在最初提交事務時會同更改更新到數據庫。以下:
public void testSave2(){ Session session=null; Transaction tx = null; try{ session=HibernateUtils.getSession(); //開啟事務 tx= session.beginTransaction(); //Transient狀況 User user=new User(); user.setName("zhangsi"); user.setPassword("123"); user.setCreateTime(new Date()); user.setExpireTime(new Date()); //persistent狀況 //persistent狀況的對象,當對象的屬性產生轉變的時刻 //Hibernate在清算緩存(髒數據檢討)的時刻,會和數據庫同步 session.save(user); user.setName("lisi"); tx.commit(); }catch(Exception e){ e.printStackTrace(); if(tx != null){ tx.rollback(); } }finally{ HibernateUtils.closeSession(session); } //detached狀況 }
檢查上例運轉成果視圖:
剖析成果:session在提交事務的時刻其實做了兩部的操作,聯合代碼中的更新進程,起首是新增了一個User對象,以後履行了save操作,它會挪用insert語句,然後在代碼中做了一個setName的操作,從新修正了稱號,但這時候還沒有同步到數據庫中而是在內存中,這時候就會有兩種狀況,我們稱此時的數據位髒數據,最初提交事務的時刻更新到數據庫中。