對象保存在內(nèi)存中,內(nèi)存不能永久保存數(shù)據(jù)翻屈,如果要永久保存就需要對象持久化(將對象存儲到數(shù)據(jù)庫中).
關(guān)系型數(shù)據(jù)庫存放關(guān)系型數(shù)據(jù)陈哑,它是非面向?qū)ο蟮模瑢ο蠛完P(guān)系數(shù)據(jù)都是業(yè)務(wù)實體的兩種表現(xiàn)形式伸眶,業(yè)務(wù)實體在內(nèi)存中表現(xiàn)為對象惊窖,在數(shù)據(jù)庫中表現(xiàn)為關(guān)系數(shù)據(jù).
內(nèi)存中的對象之間存在關(guān)聯(lián)和繼承關(guān)系,而在數(shù)據(jù)庫中厘贼,關(guān)系數(shù)據(jù)無法直接表達多對多關(guān)聯(lián),繼承關(guān)系等
因此界酒,把對象持久化到關(guān)系數(shù)據(jù)庫中,需要進行對象-關(guān)系的映射(Object Relation Mapping)即ORM
持久化為什么不使用JDBC嘴秸?
- JDBC是java中最原始和最直接的訪問關(guān)系型數(shù)卡的方式
- JDBC優(yōu)點是運行效率高
- JDBC缺點是java程序中嵌入大量sql語句,使得項目難以維護
- 如果關(guān)系型數(shù)據(jù)庫關(guān)系很復雜毁欣,業(yè)務(wù)邏輯很混亂,那么使用JDBC編程實現(xiàn)持久化需要更專業(yè)的知識(比如:緩存機制岳掐,日志等)
hibernate API分類
- 提供訪問數(shù)據(jù)庫(增刪改查)的接口( Session, Transaction, Query )
- 配置Hibernate接口:Configuration
- 使應(yīng)用程序攔截Hibernate內(nèi)部發(fā)生的事情凭疮,不做出反應(yīng),這些接口包括:Interceptor, LoadEventListener, SaveEventListener等
- 擴展Hibernate功能的接口串述,UserType, CompositeUserType, IndentiFierGenerator等执解,如有需要應(yīng)用程序可以擴展這些接口;
- hibernate內(nèi)部封裝了JDBC, JTA, JNDI, 其中JTA和JNDI使hibernate能夠和JavaEE應(yīng)用服務(wù)器集成纲酗;
hibernate核心接口
- Configuration接口:
Configuration對象用于配置, 啟動hibernate 材鹦,
hibernatey應(yīng)用通過Configuration對象獲取對象-關(guān)系映射文件中元數(shù)據(jù)庫逝淹,以及動態(tài)配置hibernate屬性;創(chuàng)建SessionFactory對象 - SessionFactory接口 :
- 初始化Hibernate, 創(chuàng)建Session對象
- 是線程安全的桶唐,意味著同一個實例可以被多個線程共享;
- 重量級的茉兰,不能隨意創(chuàng)建和銷毀他的實例尤泽,如果應(yīng)用只訪問一個數(shù)據(jù)庫,只需要創(chuàng)建一個SessionFactorys實例规脸;
- 如果同時訪問多個數(shù)據(jù)庫坯约,則需要為每個數(shù)據(jù)庫創(chuàng)建單獨的一個SessionFactorys實例.
- SessionFactory之所以是重量級別的,是因為它需要一個較大的緩存莫鸭,用來存放預定義的sql語句以及映射元數(shù)據(jù)等.我們還可以為SessionFactory配置一個緩存插件闹丐,該插件叫做Hibernate的第二級緩存,該緩存用來存放被工作單元讀過的數(shù)據(jù)被因,將來其他工作單元可能會重用這些數(shù)據(jù)卿拴,因此這個緩存中的數(shù)據(jù)可以被所有工作單元共享,一個工作單元通常對應(yīng)一個數(shù)據(jù)庫事務(wù)梨与;
- Session接口:
- 負責增堕花,刪,改粥鞋,加載/查對象
- 也稱為持久化管理器
- 和HttpSession沒有任何關(guān)系
- 不是線程安全的缘挽,因此在使用過程中應(yīng)避免多個線程共享同一個session實例
- 輕量級的,創(chuàng)建和銷毀不會銷毀太多資源呻粹,意味著程序中可以經(jīng)常創(chuàng)建和銷毀Session實例壕曼;
- Session有一個緩存,被稱為Hibernate的第一級緩存等浊,存放的是當前工作單元加載的對象腮郊,每個Session實例都有自己的緩存,該緩存只能被當前工作單元訪問凿掂;
- Transaction接口:管理事務(wù)
- Query和Cirteria接口:
- 執(zhí)行復雜數(shù)據(jù)庫查詢伴榔;
- Query包裝了HQL查詢語句,與Sql相似庄萎,但是HQL查詢是面向?qū)ο蟮淖偕伲妙惷约皩倜皇潜砻妥侄蚊?/li>
- Criteria接口封裝了基于字符串的查詢語句糠涛,比query接口更加面向?qū)ο笤荩珻riteria接口擅長進行動態(tài)查詢;
事務(wù)處理接口
當程序通過Hibernate來加載忍捡,保存集漾,更新切黔,刪除對象時,會觸發(fā)Hibernate攔截器以及事件監(jiān)聽器做處理具篇;
映射類型接口
org.hibernate.type.Type接口表示將域?qū)ο髷?shù)據(jù)類型映射為數(shù)據(jù)庫的關(guān)系數(shù)據(jù)纬霞,Hiberate為Type實現(xiàn)了各種實現(xiàn)類,比如:InterType, FloatType等
可擴展的接口
一.hibernate功能
- hibernate是開源的
- ORM映射
- 是java領(lǐng)域的一款開源的ORM框架技術(shù)
- 對JDBC進行了非常輕量級的對象封裝
- 是業(yè)務(wù)邏輯和數(shù)據(jù)庫中間的持久化層( 中間件 )
- 數(shù)據(jù)查詢和緩存
- 可以應(yīng)用在獨立的java程序和web應(yīng)用中驱显;
- 可以和多種Web服務(wù)器诗芜,應(yīng)用服務(wù)器良好集成
-
支持幾乎所有流行的數(shù)據(jù)庫
Paste_Image.png - 點擊查看練習代碼
二.開發(fā)工具介紹以及安裝
開發(fā)工具:Eclipse Standarg Kepler
Hibernate Tools for Eclipse Plugins
Hibernate Tools是JBoss公司推出的一個Eclipse綜合開發(fā)工具插件,該插件可以簡化ORM框架Hibernage, 以及JBoss Seam, EJB3等的開發(fā)工作,所以在Eclipse中安裝Hibernate Tools之前要先確認Eclipse版本埃疫,在找對應(yīng)的Hibernate Tools版本伏恐,我的eclipse版本是Eclipse Mars 4.5.2,以下是具體Hibernage Tools安裝步驟,
參考文章
-
點擊Eclipse -> Help -> Eclipse Marketplace
Paste_Image.png 在Find中輸入Hibernate找到JBoos Tools栓霜,選中下一步后只把Hibernate Tools選中翠桦,然后安裝,
-
安裝完畢后重啟Eclipse胳蛮,選擇File->new->輸入Hibernate销凑,以下圖片代表安裝成功
Paste_Image.png
三.開發(fā)前準備
- 導入Hibernate jar包
- 首先要知道自己的Hibernate版本,我在eclipse目錄下的plugins中找到的hiberate版本為org.hibernate.eclipse.console_5.0.1.Final-v20160331-1852-B88我的理解為5.0.1.Final鹰霍,可以 點擊下載
- 下載后將hibernate-release-5.0.1.Final.zip解壓闻鉴,hibernate-release-5.0.1.Final/lib/required目錄下就是我們要的Hibernate的jar包
- 在eclipse中點擊window -> Preferences-> java -> Build Path -> User Liberies -> New,輸入hibernate-core(新建hibernate類庫)確定.
- 然后導入外部jar包茂洒,點擊Add External Jars孟岛,找到hibernate-release-5.0.1.Final/lib/required下的所有jar包并導入
- 導入junit4 jar包
- 點擊下載
- 下載的包是junit-4.10.jar
- 下載后,在eclipse中新建junit4類庫督勺,方式參考以上方式(區(qū)別就是junit只有一個jar包)
導入mysql-connector-java-5.1.38.jar
在eclipse中新建mysql-jdbc類庫方式參考以上方式.在工程中導入我們以上創(chuàng)建的三個類庫
- 創(chuàng)建java project名為 hibernate-1
- hibernate-1 右鍵 -> properties -> java Build Path -> Libraries -> Add Library -> User Library 將剛剛創(chuàng)建的三個類庫選中渠羞,點擊Finsh就可以成功導入了.
-
導入工程成功的樣子
Paste_Image.png
四.創(chuàng)建第一個Hibernate
-
創(chuàng)建hibernate配置文檔
src-> New -> other -> Hibernate -> cfg.xml
Paste_Image.png -
創(chuàng)建持久化類( 實體類 )Students
javaBeans類創(chuàng)建原則:- 類必須是公有的
- 提供公有的不帶參數(shù)的默認的構(gòu)造方法
- 屬性私有
- 屬性setter/getter封裝
-
創(chuàng)建關(guān)系對象映射文件(該文件是做數(shù)據(jù)庫字段和實體類屬性映射所用)
src-> New -> other -> Hibernate -> hbm.xml
Paste_Image.png
點擊下一步找到我們剛才建立的實體類(Student)
Paste_Image.png
最后Finsh完成; -
使用junit單元測試
注解小執(zhí)行方法的順序為:- 1.@Before: 初始化方法
- 2.@Test : 測試方法
- 3.@After : 釋放資源
建立測試項目:在Hibernate-1項目名右擊 -> New -> Source Folder ->輸入Test,在該目錄下創(chuàng)建StudentsTest類:
package firstTest;
import java.util.Date;
import javax.print.attribute.standard.MediaPrintableArea;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import entity.Students;
/**
* 測試類
* @author lxf
*
*/
public class StudentsTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
//初始化配置
public void init()
{
/*
* 注意:我的hibernate是5.0和慕課網(wǎng)上講的Hibernate4.2.4(就是4.0)兩個版本的配置方法不一樣
*/
//創(chuàng)建服務(wù)注冊對象
//如果.cfg.xml取了其他的名字智哀,要改為.configure("名字.cfg.xml")
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
//創(chuàng)建會話工廠對象
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
//創(chuàng)建會話對象
session = sessionFactory.openSession();
//開啟事務(wù)
transaction = session.beginTransaction();
}
@Test
//真實的單元測試
public void testSaveStudent()
{
Students st = new Students(1,"張三豐", "nan", new Date(), "wds");
//保存對象進入數(shù)據(jù)庫
session.save(st);
}
@After
//釋放資源
public void destroy()
{
//提交事務(wù)
transaction.commit();
//關(guān)閉會話
session.close();
//關(guān)閉會話工廠
sessionFactory.close();
}
}
在StudentsTest.java右鍵Run as -> Junit Test執(zhí)行次询,程序執(zhí)行testSaveStudent羅輯,判斷數(shù)據(jù)庫hibernate中是否有students表瓷叫,如果有則刪除屯吊,沒有則創(chuàng)建,然后將new Students(1,"張三豐", "nan", new Date(), "wds");對象屬性insert到數(shù)據(jù)庫的字段中摹菠;
五.Hibernate常用配置
-
hibernate.cfg.xml常用配置
Paste_Image.png -
Hibernate執(zhí)行流程
Paste_Image.png transaction簡介
- hibernate對數(shù)據(jù)庫的操作都是封裝在事務(wù)中盒卸,并且默認是非自動提交的方式,所以用session保存對象時次氨,如果不開啟事務(wù)蔽介,并且手工提交事務(wù),對象并不會真正保存到數(shù)據(jù)庫中;
- 如果想讓hibernate自動提交事務(wù)虹蓄,必須調(diào)用session.doWork()方法獲取jdbc的connection后犀呼,設(shè)置為自動提交,(
不推薦使用
)
@Test
//真實的單元測試
public void testSaveStudent()
{
Students st = new Students(1,"張三豐", "nan", new Date(), "wds");
session.doWork(new Work(){
@Override
public void execute(Connection connection) throws SQLException {
// TODO Auto-generated method stub
//開啟關(guān)系型數(shù)據(jù)庫的自動提交
connection.setAutoCommit(true);
}
});
//保存對象進入數(shù)據(jù)庫
session.save(st);
session.flush();
}
- session簡介
- Hibernate是對JDBC的一個封裝薇组,所以不建議使用jdbc的connection操作數(shù)據(jù)庫外臂,而是通過使用session操作數(shù)據(jù)庫;
- 可以session就是操作數(shù)據(jù)庫的對象
- session與connection是多對一的關(guān)系体箕,每個session都有一個與之對應(yīng)的connection, 一個connection不同時刻可以提供多個session使用专钉;
- 所以想把對象保存在關(guān)系型數(shù)據(jù)庫中需要調(diào)用session的各種方法,如:save(), update(), delete(), createQuery()等等累铅;
-
如果獲取session對象的兩種方式
- (1). sessionFactory.openSession()
-
(2). sessionFactory.getCurrentSession()
Paste_Image.png
openSession 和getCurrentSession區(qū)別
- openSession每次創(chuàng)建新的session對象, 而getCurrentSession使用現(xiàn)有的session對象(單例模式)
- getCurrentSession對象在事務(wù)提交或回滾后自動關(guān)閉,而openSession需要手動關(guān)閉站叼,(如果使用openSession沒有手動關(guān)閉娃兽,則會導致連接池溢出)
對象關(guān)系配置文檔hbm常用配置
參考文章單表映射
-
基本類型
Paste_Image.png -
日期類型
Paste_Image.png -
對象類型
Paste_Image.png -
組件屬性
Paste_Image.png
- 單表CURD操作
- 獲取單條數(shù)據(jù)有session.get()和session.load()
- get和load區(qū)別是:
(1) 在不考慮緩存的情況下,get方法會在調(diào)用之后立刻向數(shù)據(jù)庫發(fā)出sql語句尽楔,返回持久化對象投储;
(2)而load方法會在調(diào)用后返回一個代理對象,該代理對象只保存實體對象的id阔馋,直到使用對象的非主鍵屬性時菜會發(fā)出sql語句查詢數(shù)據(jù)庫玛荞;
(3)查詢數(shù)據(jù)庫中不存在的數(shù)據(jù)庫時,get方法返回null呕寝,而load方法則會拋出異常:org.hibernate.ObjectNotFoundException