【小資說庫】第13期 應用程序開發人員、DBA和DBMS開發人員的分工是怎樣的?
979
2025-03-31
hibernate 是一個開放源代碼的對象關系映射框架,它通過對?JDBC 進行輕量級的對象封裝,使?Java 程序員能夠隨心所欲地使用面向對象的編程思維來操作數據庫。hibernate 不僅提供了?Java類與數據表之間的映射,而且還提供了數據查詢與恢復機制。相對于?JDBC 手工操作數據庫而言,Hibernate 大大減少了操作數據庫的工作量。另外,Hibernate 能夠利用代理模式簡化載入類的過程,大大減少了利用?Hibernate QL 從數據庫提取數據代碼的編寫工作量,節約了開發時間及成本。Hibernate 能夠與多種?Web 服務器或者應用服務器良好地集成,基本上支持所有流行的數據庫服務器。本章主要通過引人持久層及分層結構介紹?Hibernate。
Hibernate是一種Java語言下的對象關系映射解決方案。 它是使用GNU寬通用公共許可證發行的自由、開源的軟件。它為面向對象的領域模型到傳統的關系型數據庫的映射,提供了一個使用方便的框架。Hibernate也是目前Java開發中最為流行的數據庫持久層框架,現已歸JBOSS所有。
它的設計目標是將軟件開發人員從大量相同的數據持久層相關編程工作中解放出來。無論是從設計草案還是從一個遺留數據庫開始,開發人員都可以采用Hibernate。
Hibernate不僅負責從Java類到數據庫表的映射(還包括從Java數據類型到SQL數據類型的映射),還提供了面向對象的數據查詢檢索機制,從而極大地縮短的手動處理SQL和JDBC上的開發時間。從上面的介紹中我們看到了兩個關鍵詞,對象關系映射(ORM) 和持久化(層)那么什么是持久化?
1.1?持久化與持久層
1.1.1?什么是持久化
Hibernate是一個優秀的java持久層解決方案,是當今主流的對象-關系映射工具但是何為持久化。
程序運行的時候,有些程序數據保存在內存中,當程序退出后 ,這些數據就不復存在了,所以我們稱這些數據為瞬時的(transient)。有些數據在程序退出后,需要進行保存到存儲設備上(硬盤,光盤)中,我們稱這些數據的狀態是持久的(Persistent),持久的數據在程序再次運行的時候是可以恢復、重用的。
持久化就是將有用的數據以某種技術進行保存,以備日后再次取出應用的方法。將內存數據以文件形式保存在永久介質?(磁盤等)中,持久化可以通過將程序數據直接保存成文本文件或者XML格式等手段實現,但平時我們所說的持久化一般是指基于關系型數據庫的持久化。
狹義上的對象持久化是指將域對象永久保存至數據庫中,而廣義上的對象持久化則包括與數據庫相關的各種操作。
(1)保存:將域對象永久保存至數據庫中。
(2)更新:更新數據庫中域對象的狀態。
(3)刪除:從數據庫中刪除域對象。
(4)加載:根據特定的?OID,將域對象由數據庫加載至內存。
(5)查詢:根據特定的查詢條件,將符合查詢條件的一個或多個域對象從數據庫加載至內存。
1.1.2??持久層
隨著計算機軟件的發展,應用程序逐漸由最初的單層結構體系向多層結構體系發展。最初的應用軟件只是在大型機上使用單層結構,主要以文件系統的方式存儲數據。隨著數據庫技術的成熟,應用軟件由單層向雙層發展。在雙層應用中,主要包括存放數據的數據庫層以及將視圖同業務邏輯混合的應用層。例如,一個JSP文件包括網頁代碼、接收請求與響應的代碼以及處理業務邏輯的代碼。這種分層方法使程序結構不夠清晰,維護十分困難,在大型項目中此缺點尤為突出。因此,三層結構及多層結構應運而生。應用程序的分層體系結構發展如圖?1. 1. 2?所示。
三層結構是如今最典型的一種應用軟件分層結構,三層分別為:
(1)表述層:提供與用戶交互的界面,主要包括圖形用戶界面GUI及Web 頁面。
(2)業務邏輯層:主要負責解決、實現特定業務領域的需求。例如,在刪除班級時,業務邏輯層首先獲取該班級的所有學生信息并刪除,然后再刪除班級。
(3)數據層:對應用的業務數據進行存儲與管理。例如,在學員管理系統數據庫中,對學生、班級等業務數據進行保存。
由三層結構可知,業務邏輯層不僅負責業務邏輯,而且直接訪問數據庫,提供業務數據的增、刪、改、查等功能。為了將數據庫訪問細節與業務邏輯分開,可以將數據訪問獨立出來作為持久層。重新分層的軟件結構如圖?1.1.3示。
當前應用系統設計中,MVC 已是主流系統架構模式,貫穿了整個設計流程。其中,V (View)與?C(Controller)分別指視圖與控制器,M (Model)是業務邏輯與數據庫邏輯之間的橋梁。持久層作為業務邏輯層中最主要的組件,其設計的好壞直接影響系統的整體表現,是系統中至關重要的一環。
Mvc設計模式與四層應用結構的對應關系見圖?1.1.4所示。
所謂“持久層”,是指在系統邏輯層面上專注于實現數據持久化的一個相對獨立的領域?(Domain)。持久層是負責向一個或者多個數據存儲器中存儲?(或者獲取)數據的一組類及組件,必須包括一個業務領域的實體模型?(即使只是一個元數據模型)。
持久層封裝了數據訪問的細節,為業務邏輯層提供面向對象的?API。Hibernate就是當今最為流行的一種持久層解決方案。
1.2 ?ORM和Hibernate
JDBC是最為常見的一種持久層實現技術,使用JDBC可以較為方便的進行數據庫的操作。但是在編寫程序的時候,以面向對象的方式處理數據,保存數據的時候卻以關系型數據庫的方式存儲,面向對象的應用系統和關系型數據庫之間又存在著嚴重的不匹配 ,需要在對象和關系型數據庫之間進行轉換,這個過程極為的繁瑣和重復 ,毫無創造性,簡直令人崩潰!
在hibernate.cfg.xml中配置數據庫連接信息和Hibernate的參數如示例1.2所示。
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
oracle.jdbc.driver.OracleDriver
Hibernate配置文件的常用屬性如表1-1-1所示:
表1-1-1 ?Hibernate配置文件常用屬性
屬性
描述
hibernate.dialect
一個Hibernate Dialect類名允許Hibernate針對特定的關系數據庫生成優化的SQL
hibernate.connection.driver_class
連接數據庫的驅動程序類
hibernate.connection.url
連接數據庫的?URL
hibernate.connection.username
數據庫用戶名
hibernate.connection.password
數據庫用戶密碼
hibernate.show_sql
默認取值false,若為true,表示在程序運行時將在控制臺輸出SQL語句,有利于跟蹤Hibernate運行狀態。通常在應用開發與測試階段置為true,方便調試測試;在應用發布階段置為false,減少輸出,提高性能。
其他Hibernate常用參數的配置請參考Hibernate包中的參考手冊。
Hibernate要求使用者必須將數據庫的連接信息放到配置文件中,這樣不僅有利于項目的實施,而且降低了項目的風險,當數據庫連接信息發生變化,甚至底層數據庫發生了變化只需要修改配置文件即可,而無需修改源代碼。
4. 創建持久化類
首先定義用戶實體類(持久化類)Person.java,代碼如示例1.3所示。
public class Person implements Serializable{
private int id;
//是否被刪除
private boolean deleted;
//創建時間
private Date dateCreated;
private String account;
private String sex;
private String name;
private String birthday;
private String email;
//注冊時的ip
private String ipCreated;
//最后一次登錄時間
private Date dateLastActived;
//最后一次登錄ip
private String ipLastActived;
private String password;
//…略getter setter
}
5創建映射文件
創建實體類后還需要通知hibernate對象和數據庫表 ,對象屬性和表字段之間的對應關系,這些映射關系可以在映射文件中加以定義,然后Hibernate才可以根據映射文件工作!映射文件是是Hibernate工作的核心。
從根本上來說,Hibernate對映射文件的名稱和路徑并無強制要求,可以把所有實體類在一個映射文件中配置,也可以分開多個映射文件進行配置,但原則上我們推薦每個持久對象創建一個映射文件并以class_name.hbm.xml命名并和實體類放置在同一路徑下。
在class_name. hbm.xml 中,class_name是實體類的類名。Person.hbm.xml 的內容如示例1.4所示。
示例1.4
SEQ_ID
其中部分元素的含義如下:
class元素屬性值
(1)name:對應持久化類名。
(2)table:對應數據庫表名。
(3)dynamic-update:動態更新,默認為?false。指定用于update 的?SQL將在運行時動態地生成,且只改變更改過的字段。
(4)dynamic-insert:動態插入。指定用于insert語句的動態生成,并且只插入非空的值。
(5)select-before-update:執行update之前先執行select語句,若沒有修改則不進行?update。這通常會影響性能,但是可以防止對update觸發器進行不必要的觸發。
(6)lazy:延遲加載,默認為?true。
id元素
(1)name:標識屬性的名稱。
(2)type:標識Hibernate類型的名稱。
(3)column:對應數據庫表的主鍵字段的名稱。
(4)unsaved-value:其值用于判斷對象是否需要保存。
(5)generator:子元素用于設定標識符生成器。Hibernate提供了多種內置的實現,見表?1-1-2所示。
表1-1-2 主鍵生成策略
標識符生成器
描述
increment
適用于代理主鍵。由?Hibernate 自動以遞增的方式生成標識符,每次增量為?1。
identity
適用于代理主鍵。由底層數據生成標識符,前提條件是底層數據庫支持自動增長字段類型。
sequence
適用于代理主鍵。Hibernate 根據底層數據庠的序列來生成標識符,前提條件是底層數據庫支持序列,通過param子元素指定數據庫中使用的序列的名稱。
hilo
適用于代理主鍵。Hibernate 根據?high/low算法生成標識符,將特定表的
字段作為?high值。默認情況下選用?hibernate_ unique_key表?next_hi
字段。
native
適用于代理主鍵。根據底層數據庫對自動生成標識符的支持能力來選擇identity、sequence 或者?hilo。
uuid.hex
適用于代理主鍵。Hibernate 采用?128 位的?UUID算法來生成標識符。UUID算法能夠在網絡環境中生成唯一的字符串標識符。字符串類型的主鍵比整數類型的主鍵占用更多的數據空間,所以這種標識符生成策略并不流行。
assigned
適用于自然主鍵。由?Java 應用程序負責生成標識符,為了使?Java 應用程序設置OID,不能將?setld ()方法聲明為?private 類型。應該盡量避免使用自然主鍵。
property元素映射值類型屬性
(1)name屬性:指定持久化類的屬性的名稱。
(2)type屬性:指定?Hibernate 映射類型。Hibernate映射類型是Java類型與?SQL類型之間的橋梁。
(3)columm屬性:指定與類的屬性映射的表的字段名。
(4)update:默認為?true,指定在update時是否進行更新。
(5)insert:默認為?true,指定在insert時是否進行插入。
(6)not-null:默認為?false,指定屬性是否為空。
最后一定記得在hibernate.cfg.xml中指定映射文件的位置,這樣hibernate才能找得到!
1.4?使用Hibernate操作數據庫
1.4.1 使用Hibernate的七個步驟
經過前面的準備,我們終于可以開始使用Hibernate來操作數據庫了,但不用高興的太早,使用Hibernate需要以下7個步驟, 如圖1.1.14所示。
(1) 解析并讀取Hibernate.cfg.xml
Configuration對象用于讀取配置文件并創建?SessionFactory對象,Configuration 的構造方法是將默認路徑下的?hibernate.cfg.xml (或?hibernate.properties)配置文件中的配置信息讀入內存。如果hibernate.cfg.xml文件不是標準名稱或者路徑 可以在configure ( )中加以聲明,代碼如下:
Configuration config = new Configuration();
config.configure();
(2)讀取并解析映射文件,創建Session Factory, 代碼如下:
SessionFactory factory = config.buildSessionFactory();
一個?SessionFactory實例對應一個數據存儲源, 可由?SessionFactory 中獲得?Session 實例。
SessionFactory包括以下特點:
??線程安全。同一個實例能夠被應用的多個線程共享。
??重量級。不能隨意創建或銷毀。若應用只訪問一個數據庫,則在初始化時創建一個SessionFactory實例即可;若同時訪問多個數據庫,則需要為每個數據庫創建單獨的?SessionFactory實例。
(3)?打開Session。
在?Hibernate應用中,Session接口的使用最為廣泛,也稱為持久化管理器,提供與持久化相關的操作,如添加、更新、刪除、加載及查詢對象 ,可以簡單理解session為jdbc中Connection的封裝。代碼如下:
Session session = factory.openSession();
Session包括以下特點:
??非線程安全。在設計軟件架構時,應避免多個線程共享同一?Session實例。
??輕量級。即創建與銷毀無須消耗過多的資源,可以經常在程序中創建或銷毀?Session對象。例如,為每個客戶請求分配單獨的?Session實例,或者為每個工作單元分配單獨的Session實例。
(4)?Transaction
事務Transaction為應用程序指定以原子操作單元范圍的對象。在對數據庫進行增加、修改及刪除等操作時,必須添加?Transaction,查詢操作可選,代碼如下:
Transaction tx?= session.beginTransaction()?;
(5)數據庫操作
session.save(person);//或者其他操作
(6)提交(回滾)事物
tx.commit();(tx.rollback();)
(7)關閉session
session.close();
通過以上七步就可以完成對數據庫的各種操作,不同之處只在于最終調用session的方法不同而已,所以在項目開發中我們都會使用一個工具類來封裝這些重復步驟,代碼如示例1.5所示。
示例1.5
public class HibernateUtil {
private static Configuration config;
private final static SessionFactory factory;
static{
config=new Configuration();
config.configure();
factory = config.buildSessionFactory();
}
public static Configuration getConfig() {
return config;
}
public static SessionFactory getFactory() {
return factory;
}
public static Session getSession(){
return factory.openSession();
}
}
1.4.2 Hibernate應用
Hibernate 可用于執行增加、查詢、修改和刪除等操作。
1. 使用hibernate實現添加用戶
代碼如示例1.6所示。
示例1.6
session = HibernateSessionFactory.getSession();//獲取session
tx = session.beginTransaction();//開啟事務
session.save(person);
tx.commit();//提交事務
示例中Session 的關閉和事物回滾部分被省略。
2. 使用Hibernate實現用戶的查詢
Hibernate中提供了多種方式來獲取數據,現在給大家介紹其中最基本和簡單的方式,根據id進行檢索:
Ojbect ?get(Class clazz,Serializable id)
Ojbect ?load(Class clazz,Serializable id)
這兩個方法都是使用id進行檢索,下面的例子將展示他們的區別。
使用get方法查詢用戶的代碼如示例1.7所示。
示例1.7
Person person?= (Person)session.get(Person.class?,1);
System.out.println(person.getName());
本例中只需要一行代碼即可完成對象的獲取,無需從ResultSet中取得數據進行手工封裝。
使用load方法查詢用戶代碼如示例?1.8所示。
示例?1.8
Person person?= (Person)session.load(Person.class?,1);
System.out.println(person.getName());
Load方法在指定的id不存在的時候將會拋出異常而get方法不會,但這只是他們的區別之一,更多的區別將會在后續課程中講解。
3. ?使用Hibernate實現用戶的修改刪除
在Hibernate中操作都是針對對象的,要修改和刪除數據,首先要先獲取對象,代碼如示例1.9所示。
示例1.9
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Person person = new Person();
person.setId(1);
session.delete(person);
tx.commit();
修改數據的代碼如示例1.10所示。
示例1.10
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Person person = (Person)session.get(Person.class,1);
Person.setName(“測試”);
session.update(person);
tx.commit();
通過使用Hibernate進行增刪改查操作,我們可以看出Hibernate是面向對象進行操作的,不再需要面對數據庫、表、字段等概念。根據面向對象的語義,增刪改查方法的參數都是對象而不是主鍵。以面向對象的思維進行持久化操作是Hibernate的重要理念。
1.5?使用MyEclipse開發Hibernate
MyEclipse提供了簡化開發?Hibernate 的功能,大大地提高了開發?Hibernate的效率,減少了映射文件及配置文件的出錯率。
使用MyEclipse開發?Hibernate 的步驟如下:
??創建數據庫
創建名為“forum”的數據庫和表tb_person。其中,tb_person表包括12個字段:
id:用戶ID,主鍵 自動增長。
name:用戶名稱。
password:用戶密碼。
deleted: 刪除標志。
dateCreated:?創建時間。
sex: 性別。
birthday:生日。
email: 郵件。
ipCreated:?注冊時的ip。
dateLastActived:?最后一次登錄時間。
ipLastActived:?最后一次登錄ip。
Java 數據庫
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。