<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<!-- 數據庫別名 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- JDBC連接URL -->
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<!-- 數據庫用戶名 -->
<property name="connection.username">root</property>
<!-- 數據庫密碼 -->
<property name="connection.password">123</property>
<!-- 數據庫JDBC驅動類名 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 顯示sql語句 -->
<property name="show_sql">true</property>
<!-- 自動建表設置 -->
<property name="hbm2ddl.auto">create</property>
<!-- 需要與數據庫進行ORM映射的實體 -->
<mapping resource="com/insigma/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
對于Hibernate工具,指的是為了方便程序員的開發和調研,hibernate提供的是一些可選的功能,下面是三個常用的Hibernate工具:
show_sql 讓hibernate把底層執行的sql語句打印在控制臺上。 <property name="show_sql">true</property>
format_sql 自動格式化打印到控制臺上的sql語句 <property name="format_sql">true</property>
hbm2ddl.auto 用于自動創建數據庫表。通過它,在Hibernate每次使用之前,他會更具實體及他們之間的關系自動創建表或更改表結構。 <property name="hbm2ddl.auto">create</property>
(2),創建POJO實體:
實體,是ORM技術范疇的一個重要概念,它代表兌現現實世界的某種事物的抽象模擬,例如,用戶、學生、動物等。實體是Hibernate的基本操作單元,在開發者眼里實體就是一個數據對象,而且該數據對象是需要保存到數據庫里的。
Hibernate操作的實體是簡單的java對象,與EJB的實體bean不同,POJO實體不需要繼承任何類和實現任何接口,他就是一個最普通的java對象,它的定義方式和javabean優點類似,也需要包含一個公開的默認的無參構造方法,也是使用setter和getter方法訪問實體的屬性。
實體代表的是一類事物,那么每個實體靠什么區分開呢?與數據庫表格的主鍵類似,,實體也有主鍵,而且必須有一個主鍵,Hibernate會根據主鍵的相等與否區別實體對象。另外主鍵是一般沒有業務意義的,他僅僅用來區分不同的實體對象,常用java.lang.Lang型來定義實體對象的主鍵的。
(3),創建數據庫表:
1》手動創建。
2》通過對hibernate.cfg.xml的配置,自動創建實體對應的表格需要加上這樣的配置: <property name="hbm2ddl.auto">create</property> 在Hibernate每次使用之前,他會更具實體及他們之間的關系自動創建表或更改表結構。 當然的他的底層實現還是需要用到create等DML語言的SQL語句。
(4),映射配置文件:
映射配置文件是指明實體與數據庫之間是如何映射的,他負責告訴Hibernate從java程序到數據庫應該怎樣保存數據,以及如何從數據庫取出數據到java程序里。一般情況下,一個實體就對應一個映射配置文件。實體之間的關系也是在配置文件中進行相應配置的。
映射配置文件時采用XML格式,其內容大致是這樣的,在跟標簽<hibernate-mapping>里使用<class>標簽配置實體類,通過《class》標簽的name屬性指定實體的完整類名,table指定表名,在《class》標簽里,必須使用《id》配置實體的主鍵和生成策略,然后使用《property》標簽配置實體其他屬性的映射。另外,還有可能使用《many-to-one》《set》等標簽配置實體與其他實體的關系。
映射配置文件常用的XML標簽及其使用介紹
標簽 屬性 說明
<class> name 實體類名
table 實體對應的數據庫表名
<id> name 實體的主鍵屬性名
column 數據庫表的主鍵字段名,默認與name相同
<generator> class 主鍵生成策略
<property> name 實體的屬性名
column 數據庫表的對應的字段名,默認與name相同
not-null 是否為空,默認可以
unique 是否唯一,默認否
length 字段的最大長度
<one-to-one> 一對一
<many-to-one> 多對一
<many-to-many> 多對多
<set> 用來建立集合映射
(5)使用Hibernate API 操作數據:
一切準備就緒以后,就可以使用Hibernate提供給開發者的API的操作實體數據了。程序員使用到的主要接口和類都在org.hibernate包里。
package com.insigma;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class HibernateSessionFactory {
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}
public static Configuration getConfiguration() {
return configuration;
}
}
從以上代碼基本可以看出,使用Hibernate的步驟與jdbc有些類似,大致可以分為6步:
1》生成配置對象(Configuration)。通過調用Configuration的configure() 方法,用配置文件的設置創建配置對象,一般情況下,配置對象只需要一個。
2》創建SessionFactory對象。有配置對象創建一個SessionFactory對象,它代表了一個數據源。他的作用有一點類似于jdbc的驅動管理器,用來打開Session。一般情況,SessionFactory對象也只需一個。
3》代開session。Hibernate的Session代表了一次與數據庫的連接,程序員需要的大多數操作都需要通過它。Session自帶了一個緩存,無論是否利用Session進行數據的添加、刪除、等都要經過緩存。
4》利用Session進行各種實體操作。保存一個實體對象,可以調用Session的save(),persist(),saveorupdate()方法。HIbernate首先把沒有主鍵的實體保存保存在緩存里,然后在事務提交或調用Session.flush()方法以后把實體數據同步到數據庫里。
對于修改一個實體對象的數據,如果程序是在Session關閉之前修改的,無需調用任何方法。否則,可以調用Session的update(),merge()saveOrUpdate()方法,進行實體的重新保存。
刪除實體簡單,直接調用Session的dele()方法即可。
當需要查詢實體時,使用Session的get()和load()方法或通過Session.createQuery()產生Query對象,執行查詢語句。無論用什么方式得到的實體,都會首先放在Session緩存里。
5》事務處理.一般來說,除了查詢之外,其他的實體操作都需要使用到事務。開始-》提交-》(異常)回滾
6》關閉Session。與JDBC關閉數據庫一樣。Session的關閉會讓Hibernate及時的把緩存里的數據同步到數據庫中。
4,ID生成策略:
主鍵ID,是實體的唯一標示符,它與數據庫的主鍵相對應。主鍵對于Hibernate是至關重要的,例如當程序調用Session.saveOrUpdate()方法的時候,Hibernate會以主鍵標準去緩存里找實體對象是否存在。如果存在則執行更新操作,否則執行新增操作。所以,保證實體是主鍵的唯一是Hibernate許多的工作基礎。
主鍵的生成策略需要在實體映射配置文件中指定:常用的ID生成策略有:native、increment、sequence、assigned、identify、hilo、foreign
(1)native:根據數據庫本地的生成策略生成主鍵。例如,Oracle采用Sequence,Mysql和sqlserver采用identify,也就是將主鍵的生成工作交給數據庫完成,Hibernate不做任何管理。
(2),increment:插入數據的時候Hibernate會給主鍵添加一個自增的主鍵,一個Hibernate實例就維護一個計數器,所以在多個實例運行的時候就不能使用這個方法。
(3)Sequence調用數據庫的sequence來生成主鍵,要設定序列名,不然hibernate無法找到,一般針對oracle使用。
(4)assigned插入數據的時候主鍵有程序自己添加,hibernate不做任何管理。
(5),identify:自增字段功能。不適合Oracle
(6),該策略稱作高低策略,它是保障生成的結果具有唯一性的算法。需要在數據庫中建立一張額外的表,默認的表明為 hibernate_unique_key,默認的字段為integer類型名稱為,next_hi也可以通過配置指定表名和字段名。
(7),采用外鍵來生成主鍵,表的主鍵是其他表的外鍵,也就是用其他表的外鍵來生成自己的表的主鍵。該策略常用與一對一的映射關系。
5,關系映射:關系映射指的是實體之間的關系與數據庫表之間的關系相互對應的過程。建立關系映射之后,當程序員操作這些實體以及與之有關聯的實體的時候,就可以吧關系的操作同步到數據庫中,數據庫則一般表現為外鍵的各種操作。
三種映射關系:一對一、一對多,多對多
6,繼承映射:
繼承關系是面向對象思想的特有關系,而數據庫不存在繼承關系。如果要把程序里的繼承關系映射到數據庫,,就需要用主外鍵的關系模擬這種繼承關系。一般情況下,用Hibernate建立繼承關系的映射,可以有兩種解決方案,各有優點,應該根據不同的情況采用不同的映射策略。
(1)單表實現:單表繼承映射的時候,只需要定義一個映射配置文件就行了。
單表是實現繼承映射的優點在于:沒有任何的表連接,查詢的速度回相對較快,多臺查效率高。但是他把所有的數據都存放在一張表里,有可能導致表特別大,不利于后期維護,而且子類的屬性很多,可能會有很多的null值,所以單表實現繼承映射更適合數據量小,,屬性個數小或多臺查詢比較多的情況。
(2)每個子類一張表實現:優點在于數據存儲的比較緊湊,當查詢某個子類數據時比較快。但是由于有很多的連接,不太適合多臺查詢,更適合側重操作某一類數據的情況。所以多表實現的繼承映射比較適合數據量大、子類屬性個數多或經常查詢某一子類的情況。
7,實體對象的生命周期:
實體。作為數據的一種裝載單元,他在Hibernate的管理過程中,回不斷的發生數據和狀態的變化。Hibernate不僅僅是一個ORM的API工具,他還是一個容器,他可以幫你管理實體對象的生命周期,這個容器就是Session的緩存。
Hibernate實體對象的三種狀態:瞬時態、持久態、托管態。實體對象的狀態會隨著Hibernate的API的調用而發生變化,開發者也應該根據實體對象的狀態的不同而使用不同的API。
瞬時態:有new語句開辟內存空間的心Jjava對象。如果沒有沒有變量對該對象進行引用,他將被java虛擬機回收。
瞬時對象在內存孤立,它是攜帶信息的載體,不和數據庫的數據有任何的關聯關系。最大的特點沒有主鍵。在Hibernate中,可通過Session的save()或saveOrUpdte()等方法將瞬時對象和數據庫關聯,并將數據同步到數據庫中。此時該瞬時對象轉化為持久化對象。
持久態:處于持久態的對象在數據庫中具有對應的記錄,并有一個持久化標志。如果是用Session的delete()方法,對應的持久對象,就變成瞬時對象,因數據庫中的對應數據已被刪除,該對象不再關聯數據庫中任何的記錄。當執行Session的close clear、evict方法之后,此時持久對象變成托管對象仍具有數據庫識別值。他已不再Hibernate持久層的管理之下了。持久對象具有兩個特點:具有主鍵且數據庫中肯定有響應的記錄。
托管態:當與某持久對象關聯的Session被關閉之后,持久變脫托管。當托管對象被重新關聯到Session上時,轉變為持久。托管對象具有數據庫的識別值。可通過update,saveOrUpdate方法轉變為持久對象。特點:本質上和瞬時對象一樣,在沒有任何變量引用的時候,jvm會在適當的時候回收,但是擁有主鍵。
8,Hibernate中的查詢功能:hibernate提供的實體查詢功能是非常強大的,他不僅可以完成一般sql可以完成的功能,還可以智能的幫助開發者完成一些工作,例如自動填充數據,關聯加載、跨數據庫實現分頁查詢等
(1)用get()和load()方法獲取單個實體對象
根據主鍵去查詢實體,是最常見也是最簡單的查詢。使用Hibernate非常簡單,只需要調用get()和load()方法即可。他們的參數列表相同,第一個是實體的類型或完整類名,第二個是主鍵。查詢得到的實體對象,都進入持久態。盡管兩種方法作用類似,但是意義卻有些不同。get是去數據庫獲取實體對象,沒有放回null而load()的意義在于把指定主鍵的實體對象加載到緩存里。如果沒有的話,Hibernate拋出ObjectNotFoundException異常。
(2)HQL查詢語言
HQL是Hibernate提供給開發者以面向對象的思想進行實體添加、刪除、等操作的查詢語言,他看起來和sql比較相似,但是它提供了更加豐富和靈活的查詢特性,同時也提供了面向對象的封裝。
1,實體查詢:
最簡單的實體查詢就是直接使用from加實體名。
String hql=“from User”;
List list=Session.CreateQuery(hql).list();
HQL與標準SQl相似,也可以在HQl語句中使用where,并且可以再where字句中使用表達式、比較操作符、以及使用and、or連接不同查詢條件的組合。
2,實體的更新和刪除。
與sql優點類似
開始事務
String hql=“”;
Query q=Session.CreateQuery(hql);
int ret=q.executeUpdate();
提交事務
3,屬性查詢:
有的時候,檢索數據并不需要獲得實體對應的全部數據,而只需檢索出實體對應的部分數據,這時就可以利用HQL的屬性查詢你技術:
4,排序和分組:
(1)order by子句
與sql語句相似,HQL查詢語句也可以使用order by子句對查詢結果進行排序,并且可以通過asc和desc關鍵字指定排序方式。
(2)group by 子句和統計查詢
在HQl語句中同樣支持使用group by子句分組查詢。還支持group by子句結合聚集函數的分組統計查詢。大部分標準的聚集函數都可以在HQL語句中使用。
5,參數綁定:
Hibernate對動態參數綁定提供了豐富的支持,HQL也像JDBC的Preparedstatement一樣,也可以只用占位符實現參數動態綁定。而且提供了更豐富的特性。在Hibernate中共提供了3中參數綁定方式。
(1)按參數名綁定。
在HQl語言中,定義命名參數使用“:”開頭;
(2)用?來定義參數的位置
(3)setparameter()方法
5,分頁查詢
Hibernate實現分頁查詢的功能支持非常好,可以說程序員使用分頁查詢是傻瓜式的,簡單到了極致,只需通過調用兩個方法告訴Hibernate從哪行開始和最多的行數其他的細節就交給Hibernate了。
6,延遲加載
延遲加載是Hibernate關聯關系的實體對象默認的加載方式,延遲加載機制是為避免一些無謂的性能開銷而提出來的。所謂的延遲加載就是在真正需要數據的時候,才真正執行數據加載操作,可以簡單的理解為,只用在使用的時候,才發出sql語句進行查詢。
延遲加載第一種保障性能的技術,不一定要使用。可以通過在映射文件里進行設置不使用延遲加載。