ORM(Object/ReLationshop Mapping):對(duì)象關(guān)系映射,盡量少寫與底層相關(guān)的sql語(yǔ)句转绷,便于維護(hù)。Hibernate為ORM框架
1)Hibernate簡(jiǎn)介
Hibernate是java領(lǐng)域的一款開源的ORM框架技術(shù)
Hibernate對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝
2)Hibernate在我們的應(yīng)用程序中充當(dāng)著什么樣的角色呢毁嗦?
舉例瓜挽,如下圖所示:我們要開發(fā)不同的系統(tǒng)
持久化層 --- 處于業(yè)務(wù)邏輯層和數(shù)據(jù)庫(kù)之間的一個(gè)角色
作用 -- 把程序中生成的對(duì)象持久化到數(shù)據(jù)庫(kù)中,換句話說(shuō)么库,就是把這些對(duì)象通過(guò)對(duì)象關(guān)系映射保存到數(shù)據(jù)庫(kù)的表中
3)其他主流的ORM框架技術(shù)
①M(fèi)yBtis : 前身就是著名的iBatis
②Toplink:后被Oracle收購(gòu)傻丝,并重新包裝為Oracle AS TopLink
③EJB:本身是JAVAEE的規(guī)范
JUnit測(cè)試
@Test 測(cè)試方法
@Before 初始化方法
@After 釋放資源
執(zhí)行順序:@Before --> @Test --> @After
hibernate中獲得數(shù)據(jù)庫(kù)連接
//創(chuàng)建配置對(duì)象
Configuration config = new Configuration().configure();
//創(chuàng)建服務(wù)注冊(cè)對(duì)象
ServiceRegistry serviceRegistery = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
//創(chuàng)建會(huì)話工廠
SessionFactory sessionFactory = config.buildSessionFactory(serviceRegistery);
//創(chuàng)建會(huì)話對(duì)象
Session session = sessionFactory.openSession();
//開啟事務(wù)
Transaction transaction = session.beginTransaction();
hibernate常用配置
hibernate前綴可以省略。
hibernate執(zhí)行流程:
Configuration讀取配置文檔hibernate.cfg.xml文檔 讀取文檔為了創(chuàng)建sessionfactory對(duì)象诉儒,創(chuàng)建session工廠對(duì)象時(shí)讀取映射文件一般之創(chuàng)建一個(gè) 然后獲取session(數(shù)據(jù)庫(kù)連接對(duì)象)執(zhí)行session方法之前必須開啟事物提交事物后session 事物transaction
Transaction事務(wù)簡(jiǎn)介:
- hibernate對(duì)數(shù)據(jù)庫(kù)的操作都是封裝在事務(wù)當(dāng)中的葡缰,并且默認(rèn)是非自動(dòng)提交的方式。所以用session保存對(duì)象時(shí)忱反,如果不開啟事務(wù)并且沒(méi)有手工提交事務(wù)泛释,對(duì)象并不會(huì)真正保存在數(shù)據(jù)庫(kù)中。
- 如果你想讓hibernate像jdbc那樣自動(dòng)提交事務(wù)温算,必須調(diào)用session對(duì)象的doWork()方法怜校,獲得jdbc的connection后,設(shè)置其為自動(dòng)提交事務(wù)模式(注意:通常并不推薦這樣做)
綜上注竿,我們必須開啟事務(wù)茄茁。
使用Session的doWork()方法提交事務(wù)(需要重寫execute()方法)。
需要注意的是:在使用save()方法后并不會(huì)真正輸出sql語(yǔ)句蔓搞,需要調(diào)用flush()強(qiáng)制輸出sql語(yǔ)句才可以胰丁。然后因?yàn)椴捎昧俗詣?dòng)提交方式(setAutoCommit(true)),數(shù)據(jù)才真正保存在數(shù)據(jù)庫(kù)喂分。
openSession與getCurrentSession區(qū)別:
1:openSession 每次使用都是打開一個(gè)新的session,使用完需要調(diào)用close方法關(guān)閉session机蔗;不關(guān)閉session會(huì)導(dǎo)致連接池溢出蒲祈。
2:getCurrentSession 是獲取當(dāng)前session對(duì)象,連續(xù)使用多次時(shí)(即使關(guān)閉了上一個(gè)session萝嘁,再次獲取一個(gè) session梆掸,獲取到的仍然是同一個(gè)session對(duì)象),得到的session都是同一個(gè)對(duì)象牙言;
另外酸钦,事務(wù)提交或回滾后,會(huì)自動(dòng)關(guān)閉session對(duì)象咱枉。
3:一般在實(shí)際開發(fā)中卑硫,往往使用getCurrentSession多徒恋,因?yàn)橐话闶翘幚硗粋€(gè)事務(wù),所以在一般情況下比較少使用openSession欢伏;
hibernate-mapping標(biāo)簽:
class標(biāo)簽:
batch-size:抓取策略入挣,表示一次可以抓取多少記錄。
id標(biāo)簽:
(子標(biāo)簽表示主鍵生成策略)
主鍵生成策略:
單一主鍵主鍵生成策略
native:mysql下為auto_increment,從1開始
assigned:程序中手工賦值,注意對(duì)象在實(shí)例化時(shí)id屬性自動(dòng)初始化為0了
hibernate映射類型硝拧、java數(shù)據(jù)類型径筏、sql數(shù)據(jù)類型的對(duì)應(yīng)關(guān)系
即在xxx.hbm.xml中<id>或者<property>的type屬性,一般用hibernate映射類型或java數(shù)據(jù)類型
1.基本數(shù)據(jù)類型
對(duì)象類型:
組件屬性<component name="某類的對(duì)象" class="剛才的某類">
get與load的區(qū)別:
1.get調(diào)用后直接發(fā)出sql語(yǔ)句獲取對(duì)象,load調(diào)用后返回一個(gè)存有id(主鍵)的代理對(duì)象,當(dāng)程序中需要使用這個(gè)對(duì)象的其他屬性時(shí)才調(diào)用sql語(yǔ)句獲取對(duì)象
2.當(dāng)找不到相應(yīng)數(shù)據(jù)時(shí),get返回null,load拋出異常org.hibernate.ObjectNotFoundException
總結(jié):
1.什么是ORM?為什么使用Hibernate障陶?
對(duì)象關(guān)系映射滋恬;為了少寫和底層數(shù)據(jù)庫(kù)相關(guān)的sql語(yǔ)句,方便程序的維護(hù)抱究、修改夷恍,提高跨平臺(tái)性和可擴(kuò)展性。Hibernate是Java領(lǐng)域內(nèi)的一款技術(shù)成熟穩(wěn)定的ORM框架
2.Hibernate開發(fā)的基本步驟媳维?
(1)編寫配置文檔hibernate.cfg.xml
(2)編寫實(shí)體類酿雪。注意:每一個(gè)實(shí)體類都要與數(shù)據(jù)庫(kù)中的一張表一一對(duì)應(yīng),實(shí)體類的編寫要遵循JavaBean的要求侄刽。
(3)生成對(duì)應(yīng)實(shí)體類的映射文件并添加到配置文檔中
(4)調(diào)用Hibernate API進(jìn)行測(cè)試
3.什么是session?
類似于JDBC里面的connection對(duì)象指黎。調(diào)用session操作數(shù)據(jù)庫(kù),實(shí)際上就是調(diào)用connection的各種API函數(shù)來(lái)實(shí)現(xiàn)的州丹。
4.openSession與getCurrentSession的區(qū)別醋安?
前者每次都是創(chuàng)建新的session對(duì)象,而后者使用單例模式墓毒,每次創(chuàng)建都是相同的對(duì)象吓揪。openSession在使用完畢后需要顯式地關(guān)閉,而getCurrentSession在事務(wù)提交之后會(huì)自動(dòng)關(guān)閉所计。
5.單表操作有哪些常用的方法柠辞?
增刪改查對(duì)應(yīng)使用session當(dāng)中的save、delete主胧、update叭首、get/load方法
6.單表操作,查詢一條記錄時(shí)踪栋,get和load的區(qū)別焙格?
get在使用的時(shí)候立即發(fā)送sql語(yǔ)句,并且獲得的是實(shí)體類的對(duì)象類型夷都,而load只有在使用具體對(duì)象的非主屬性的時(shí)候才會(huì)發(fā)送sql語(yǔ)句眷唉,而且返回的是一個(gè)代理對(duì)象。
單向多對(duì)一關(guān)聯(lián)
·多對(duì)一的關(guān)系和關(guān)系數(shù)據(jù)庫(kù)中的外鍵參照關(guān)系最匹配,即在己方的表中的一個(gè)外鍵參照另一個(gè)表的主鍵
·通過(guò)在多方持有一方的引用實(shí)現(xiàn)冬阳,需要在“多”端的一端使用<many to one> 配置
<many-to-one name="grade" class="com.imooc.entity.Grade" column="gid" cascade="all"></many-to-one>
</class>
inverse屬性;
1蛤虐、一方的hbm.xml文件的<set>節(jié)點(diǎn)的inverse屬性指定了關(guān)聯(lián)關(guān)系的控制方向,默認(rèn)由one方來(lái)維護(hù)摩泪;
2笆焰、關(guān)聯(lián)關(guān)系中,inverse="false"則為主動(dòng)方见坑,由主動(dòng)方負(fù)責(zé)維護(hù)關(guān)聯(lián)關(guān)系嚷掠;
3、在一對(duì)多關(guān)聯(lián)中荞驴,設(shè)置one方的inverse為true,這將有助于性能的改善不皆。
cascade屬性:
1、當(dāng)設(shè)置了cascade屬性不為none時(shí)熊楼,Hibernate會(huì)自動(dòng)持久化所關(guān)聯(lián)的對(duì)象霹娄;
2、cascade屬性的設(shè)置會(huì)帶來(lái)性能上的變動(dòng)鲫骗,需要謹(jǐn)慎設(shè)置犬耻;
————————————————————————————
屬性值 含義和作用
all 對(duì)所有操作進(jìn)行級(jí)聯(lián)操作
save-update 執(zhí)行保存和更新操作時(shí)進(jìn)行級(jí)聯(lián)操作
delete 執(zhí)行刪除時(shí)進(jìn)行級(jí)聯(lián)操作
none 對(duì)所有操作不進(jìn)行級(jí)聯(lián)操作
————————————————
說(shuō)明:
1.在向Grade添加Student后,保存Grade對(duì)象時(shí)执泰,能不能不需要顯示的保存Student對(duì)象枕磁,答案是可以的,可以使用級(jí)聯(lián)操作:在Grade的映射文件中的<set>節(jié)點(diǎn)添加cascade屬性不為none,為"save-update"术吝;
2.在向Student添加Grade后计济,保存Student對(duì)象時(shí),能不能不需要顯示的保存Grade對(duì)象排苍,答案是可以的沦寂,可以使用級(jí)聯(lián)操作:在Student的映射文件中的<many-to-one>節(jié)點(diǎn)添加cascade屬性不為none,為"save-update".
單向一對(duì)多:
單向多對(duì)一:
HQL定義:
1、HQL:Hibernate Query Lauguage淘衙,Hibernate查詢語(yǔ)言传藏;
2、HQL是面向?qū)ο蟮牟樵冋Z(yǔ)言(即以面向?qū)ο蟮慕嵌冗M(jìn)行查詢)幔翰,它查詢的主體是映射配置的持久化類及其屬性漩氨,與SQL查詢主體是數(shù)據(jù)庫(kù)表是完全不同的,除此之外遗增,從數(shù)據(jù)庫(kù)查詢方面的功能上來(lái)講,SQL能實(shí)現(xiàn)的數(shù)據(jù)庫(kù)查詢功能款青,HQL幾乎可以同樣實(shí)現(xiàn)做修。實(shí)際上作為一個(gè)ORM對(duì)象關(guān)系映射框架,Hibernate框架會(huì)將編寫好的HQL語(yǔ)句解析成SQL語(yǔ)句來(lái)完成最終的數(shù)據(jù)庫(kù)查詢操作。
3饰及、HQL提供了豐富靈活的查詢特性蔗坯,是Hibernate官方推薦查詢方式。
Query接口簡(jiǎn)介
1.org.hibernate.Query接口定義有執(zhí)行查詢的方法(該方法完成HQL語(yǔ)句的解析與執(zhí)行過(guò)程燎含,并返回查詢的結(jié)果宾濒。就像SQL語(yǔ)句沒(méi)有jdbc接口,它也就是普通的字符串變量屏箍,HQL語(yǔ)句也一樣绘梦,編寫好的HQL語(yǔ)句也就是一個(gè)普通的字符串變量,而hibernate框架就負(fù)責(zé)解析HQL語(yǔ)句赴魁,然后根據(jù)配置信息生成相應(yīng)的SQL語(yǔ)句來(lái)執(zhí)行數(shù)據(jù)庫(kù)的查詢操作卸奉,那么完成這個(gè)過(guò)程依靠的就是Query接口);
2.Query接口支持方法鏈編程風(fēng)格颖御,使得程序代碼更為簡(jiǎn)潔(方法鏈編程:調(diào)用方法后榄棵,返回的結(jié)果依然是調(diào)用這個(gè)方法的對(duì)象,可以在調(diào)用方法后直接調(diào)用該對(duì)象的其他方法潘拱,這樣可以使用一個(gè)程序語(yǔ)句完成多個(gè)方法的調(diào)用與執(zhí)行疹鳄。在Query接口中,方法鏈編程使用最多的場(chǎng)景是查詢參數(shù)的動(dòng)態(tài)設(shè)置芦岂,特別是多個(gè)參數(shù)的設(shè)置)
3.Query實(shí)例的創(chuàng)建:
a.Session的createQuery()方法創(chuàng)建Query實(shí)例
b.createQuery方在調(diào)用時(shí)需要傳遞一個(gè)參數(shù)(即要查詢的HQL語(yǔ)句),createQuery(hql)
4.Query執(zhí)行查詢
a.Query接口的list()方法執(zhí)行HQL查詢
b.list()方法返回結(jié)果數(shù)據(jù)類型為java.util.List,List集合中存放符合查詢條件的持久化對(duì)象
from子句
from子句是HQL語(yǔ)句的最簡(jiǎn)形式瘪弓,換句話說(shuō),HQL語(yǔ)句只需要from子句就可以執(zhí)行查詢了盔腔,這是為什么呢杠茬?
這是因?yàn)閒rom子句指定了HQL語(yǔ)句查詢的主體----映射配置的持久化類及其屬性,當(dāng)我們編寫的HQL語(yǔ)句只有from子句的時(shí)候弛随,HQL框架默認(rèn)就是查詢?cè)摮志没惖乃袑?shí)例以及該持久化類映射配置的信息瓢喉,當(dāng)HQL框架將HQL解析成SQL時(shí),就會(huì)查詢?cè)摮志没愑成涞臄?shù)據(jù)表中的所有映射字段信息舀透,并將返回的查詢結(jié)果封裝成該持久化類的list集合
distinct的使用
select distinct s.star from Seller s
使用distinct去除s.star中的重復(fù)元素