面試被問及了Hibernate框架,雖然問的很少,很簡單,但是還是簡單的總結一下吧,以備以后不時之需。
什么是Hibernate框架?
百科定義:Hibernate框架式一個開源的對象關系映射(ORM)框架,是對JDBC的輕量級的對象封裝,使java程序員可以使用對象思維來操縱DB。
白話版:在Hibernate之前,我們是如何操作DB的?JDBC,需要在程序中嵌入SQL語句。效率低下,不能忍啊。但是Hibernate的出現,讓我們無需再操縱SQL語句了,每個表實例被實例化為一個java對象,操作DB的時候,只需要操作該實例對象即可。這就是Hibernate所做的事情。是不是有一個問題:這個表實例化成什么對象呢?沒錯,需要你再手動的創建一個跟表結構(R)相對應的java類(O)。然后將這兩者相映射(M),醬子,對表的操作就完全轉換為了對類對象的操作。這就是ORM。
了解幾個概念。
瞬時狀態:在程序運行的時候,有些數據保存在內存中,當程序退出后,這些數據就不復存在了,稱這些數據的狀態是瞬時的。
持久狀態:數據以文件形式保存在輔存中,這樣,程序退出后,數據依然存在,這種狀態稱之為持久的。
持久化 :即在程序中的瞬時狀態和持久狀態之間轉換的機制。
剖析框架:(盡量用流水賬的方式講解,容易被接受)
由上圖可以看出,Hibernate框架式介於DB和應用之間的,在與App的接口部分,提供了持久化。再稍微展開來看。
PO持久化做的工作就是,將數據庫的表實例,轉換成相應類對象。同樣的,將類對象轉換為相應的表實例。
圖中hibernate.cfg.xml和Mapping是做什么用的呢?看下圖
圖中的流程可以看出:應用程序先調用Configration類,該類讀取Hibernate.cfg.xml配置文件以及Mapping映射文件,生成一個SessionFactory對象。
然后SessionFactory再生成一個Session對象。這個Session對象是與DB的一次回話。可以說是與數據庫交互的核心。增刪改查都需要通過Session。
言歸正傳:什么是Hibernate.cfg.xml配置文件和Mapping文件?
Hibernate.cfg.xml是個配置文件,你要與數據庫交互,你總得告訴人家,你的數據庫地址是多少?用戶名?密碼?(還有驅動、方言、連接池等等)具體的可以參考這里。
Mapping文件:是一個映射文件,上文中說到,我們需要知道類對象與表模型之間的對應關系,這個Mapping就是設置對應關系的。
有了這兩個文件,類<->表,算是正式的橋接上了。接下來才是面向對象操縱數據庫了。
再看Configration、SessionFactory和Session:
Configuration讀取配置文件和Mapping文件,加上其類名,因此可以想到,它可能是用來完成Hibernate的配置、初始化工作的。比如管理配置文件、鏈接數據庫、管理OR映射關系等初始化工作。
SessionFactory即會話工廠,因此肯定是生產“會話”的,會話需要知道什么?與DB會話需要知道什么?需要知道這個對象對應哪張表。因此SessionFactory才是真正的解析Mapping信息的。
Session自不必多說,與DB的一次會話。增刪改查都是在會話中進行的。只不過增刪改必須設置事務。
Hibernate就簡單介紹到這里了,把最基本的工作流程理了一下,下面附上幾個xml文件以及實例,不太明白的可以結合代碼來看。
Hibernata.cfg.xml

<?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"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <property name="connection.username">root</property> <property name="connection.url">//地址,木有寫賬號密碼... jdbc:mysql://localhost:3306/study </property> <property name="dialect">//方言 org.hibernate.dialect.MySQLDialect </property> <property name="myeclipse.connection.profile">MySQL5.0</property> <property name="connection.password">root</property> <property name="connection.driver_class">//驅動 org.gjt.mm.mysql.Driver </property> <property name="show_sql">true</property> <mapping resource="hibernate/PO/TRegister.hbm.xml" /> </session-factory> </hibernate-configuration>
Hibernate.mapping.xml

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="hibernate.PO.TRegister" table="t_register"> <id name="id" type="java.lang.Integer"> <column name="id" /> <!-- 我在MYSQL中並沒有設置該字段遞增,但在Hibernate中依然可以設置為遞增 --> <generator class="increment" /> </id> <property name="userName" type="java.lang.String"> <column name="userName" length="30" /> </property> <property name="userPwd" type="java.lang.String"> <column name="userPwd" length="30" /> </property> <property name="sex" type="java.lang.String"> <column name="sex" length="10" /> </property> <property name="age" type="java.lang.Integer"> <column name="age" /> </property> </class> </hibernate-mapping>
mapping文件中的表結構

create table T_register ( id int primary key, userName varchar(30), userPwd varchar(30), sex varchar(10), age int )
相對應的java類(與上面的表結構完全一樣,而且表屬性和類屬性在mapping.xml中完全對應)

/** * 持久化類 */ public class TRegister implements java.io.Serializable { // Fields private Integer id; private String userName; private String userPwd; private String sex; private Integer age; // Constructors /** default constructor */ public TRegister() { } /** minimal constructor */ public TRegister(Integer id) { this.id = id; } /** full constructor */ public TRegister(Integer id, String userName, String userPwd, String sex, Integer age) { this.id = id; this.userName = userName; this.userPwd = userPwd; this.sex = sex; this.age = age; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return this.userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPwd() { return this.userPwd; } public void setUserPwd(String userPwd) { this.userPwd = userPwd; } public String getSex() { return this.sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return this.age; } public void setAge(Integer age) { this.age = age; } }
hibernate具體流程實例:

** * hibernate 基礎類 * @author fengyan * date 2007-01-09 02:32 */ import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { //流程圖中第一步,解析配置文件 Configuration config = new Configuration().configure("/hibernate/hibernate.cfg.xml"); //解析Mapping映射文件,生成工廠 sessionFactory = config.buildSessionFactory(); } catch(Throwable e) { throw new ExceptionInInitializerError(e); } } public static final ThreadLocal session = new ThreadLocal(); public static Session currentSession() throws HibernateException { Session s = (Session)session.get(); //Open a new Session,if this Thread has none yet if(s == null || !s.isOpen()) { //得到session s = sessionFactory.openSession(); session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = (Session)session.get(); session.set(null); if(s != null) s.close(); } }