1.對(duì)象的幾種狀態(tài)
在所有之前桩撮,說明一下敦第,對(duì)于hibernate,它的對(duì)象有三種狀態(tài)店量,transient芜果、persistent、detached
下邊是常見的翻譯辦法:
transient:瞬時(shí)態(tài)或者臨時(shí)態(tài)
(new DeptPo(1,”行政部”,20,”行政相關(guān)”)融师,該po的實(shí)例和session沒有關(guān)聯(lián)师幕,該po的實(shí)例處于transient)
persistent:持久化狀態(tài)
(和數(shù)據(jù)庫(kù)中記錄想影射的Po實(shí)例,它的狀態(tài)是persistent, 通過get和load等得到的對(duì)象都是persistent)
detached:脫管狀態(tài)或者游離態(tài)
(1)當(dāng)通過get或load方法得到的po對(duì)象它們都處于persistent,但如果執(zhí)行delete(po)時(shí)(但不能執(zhí)行事務(wù)),該 po狀態(tài)就處于detached, (表示和session脫離關(guān)聯(lián)),因delete而變成游離態(tài)可以通過save或saveOrUpdate()變成持久態(tài)
(2)當(dāng)把session關(guān)閉時(shí)诬滩,session緩存中的persistent的po對(duì)象也變成detached
因關(guān)閉session而變成游離態(tài)的可以通過lock霹粥、save、update變成持久態(tài)
持久態(tài)實(shí)例可以通過調(diào)用 delete()變成游離狀態(tài)疼鸟。
通過get()或load()方法得到的實(shí)例都是持久化狀態(tài)的后控。
游離狀態(tài)的實(shí)例可以通過調(diào)用lock()或者replicate()進(jìn)行持久化。
save()和persist()將會(huì)引發(fā)SQL的INSERT空镜,delete()會(huì)引發(fā)SQLDELETE浩淘,
而update()或merge()會(huì)引發(fā)SQL UPDATE。對(duì)持久化(persistent)實(shí)例的修改在刷新提交的時(shí)候會(huì)被檢測(cè)到吴攒,它也會(huì)引起SQL UPDATE张抄。
saveOrUpdate()或者replicate()會(huì)引發(fā)SQLINSERT或者UPDATE
可以通過session提供的方法用于改變對(duì)象的狀態(tài)。
save()方法:
1.使一個(gè)臨時(shí)對(duì)象成為持久化對(duì)象洼怔。
2.為對(duì)象分配ID署惯。
3.在 flush緩存的時(shí)候發(fā)送一條insert語(yǔ)句。
4.save之前設(shè)置的ID是無(wú)效的镣隶。
5.持久化對(duì)象的ID是不可修改的极谊。
@Test
public void testSave() {
News news = new News();
news.setAuthor("wenyu2");
news.setDate(new Date());
news.setTitle("php");
news.setId(23);//該行設(shè)置無(wú)效
System.out.println(news);
session.save(news);
System.out.println(news);
news.setId(45);//改行拋出異常诡右。
persist()方法:
與save方法類似的是persist()方法, persist()方法也可以執(zhí)行insert操作轻猖,但是跟save的區(qū)別是帆吻,若在persist之前設(shè)置了ID值, 則拋出異常咙边,不會(huì)insert操作猜煮。
@Test
public void testPersist() {
News news = new News();
news.setAuthor("wangwu");
news.setDate(new Date());
news.setTitle("py");
news.setId(34);//拋異常,不會(huì)執(zhí)行insert操作败许。
session.persist(news);
}
get()方法:該方法會(huì)立即查詢加載數(shù)據(jù)庫(kù)中的對(duì)象(立即執(zhí)行select語(yǔ)句)王带。但是若是該記錄在數(shù)據(jù)庫(kù)中不存在那么返回一個(gè)null(沒有即沒有很直接)。
@Test
public void testGet() {
News news = (News) session.get(News.class, 4);
session.close();//若是手動(dòng)關(guān)閉session檐束,下面的打印也會(huì)成功辫秧。
System.out.println(news);
}
Load()方法:該方法功能和get相同束倍,但是屬于延遲加載的方法被丧。
也就是說,執(zhí)行l(wèi)oad方法之后绪妹,若是不使用該對(duì)象那么不會(huì)執(zhí)行select語(yǔ)句甥桂,僅僅返回一個(gè)代理對(duì)象。與此同時(shí)若是查詢的記錄在數(shù)據(jù)庫(kù)中不存在邮旷,那么會(huì)拋出異常(找不到對(duì)象)黄选,可以理解為返回代理對(duì)象之后,該代理對(duì)象無(wú)法找到與之匹配的真實(shí)對(duì)象婶肩,即拋異常办陷。
若是在使用對(duì)象之前手動(dòng)關(guān)閉了session,在使用對(duì)象的時(shí)候會(huì)拋出懶加載異常律歼。而get卻是可以打印出來(lái)民镜。
@Test
public void testLoad() {
News news = (News) session.load(News.class, 4);
System.out.println(news.getClass().getName());
session.close();
System.out.println(news);//調(diào)用的時(shí)候拋出懶加載異常。
}
update方法:
1.若更新一個(gè)持久化對(duì)象险毁,不需要顯示的調(diào)用update方法制圈,因?yàn)樵赥ransaction 的commit方法之前會(huì)先執(zhí)行flush操作(出發(fā)update語(yǔ)句)。
2.當(dāng)session關(guān)閉或者執(zhí)行了evict方法畔况,將對(duì)象從session 緩存中移除鲸鹦,那么該對(duì)象處于游離狀態(tài),此時(shí)需要顯示調(diào)用update()方法跷跪,這個(gè)update()顯示調(diào)用的時(shí)候馋嗜,不論對(duì)象的屬性是否發(fā)生變化都會(huì)執(zhí)行update語(yǔ)句,在跟觸發(fā)器協(xié)同工作的時(shí)候吵瞻,為了避免這個(gè)問題嵌戈,我們可以使用在hbm.xml文件中設(shè)置select-before-date值為true覆积,檢測(cè)是否有改變,若是沒有改變那么不會(huì)發(fā)送update語(yǔ)句熟呛。(該方式不常用)宽档。
若數(shù)據(jù)表中沒有該記錄,但是還是執(zhí)行update的話庵朝,會(huì)導(dǎo)致異常吗冤。
當(dāng)update方法關(guān)聯(lián)一個(gè)游離狀態(tài)的對(duì)象時(shí),如果session中已經(jīng)存在相同ID的持久化對(duì)象九府,會(huì)拋異常椎瘟,因?yàn)閟ession 中不能存在兩個(gè)OID相同的對(duì)象。
@Test
public void testUpdate() {
News news = (News) session.get(News.class, 4);
transaction.commit();
session.close();// 至此news對(duì)象是一個(gè)游離狀態(tài)的侄旬。
// news.setId(6);//該行會(huì)拋異常肺蔚,ID在數(shù)據(jù)表中不存在。
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// news.setAuthor("JDBC");// news既不在原來(lái)的session緩存中儡羔,也不在新的緩存中宣羊。
// News news2=(News)session.get(News.class, 5);//
session.update(news);// 也就是需要通過顯示的執(zhí)行update方法,將該對(duì)象變?yōu)槌志脿顟B(tài)汰蜘。
}
saveOrUpdate()方法:
根據(jù)是否有OID 來(lái)判斷是采用save操作還是update操作仇冯。 若OID不為空但是沒有對(duì)應(yīng)的記錄,會(huì)拋異常族操。
@Test
public void testSaveOrUpdate() {
News news = (News) new News("FF", "ff", new Date());
news.setId(34);//若該ID在數(shù)據(jù)庫(kù)中沒有對(duì)應(yīng)的記錄苛坚,拋異常。
session.saveOrUpdate(news);
}
delete方法:
可刪除一個(gè)游離對(duì)象色难,也可以刪除一個(gè)持久化對(duì)象泼舱。session 的delete方法處理過程:
計(jì)劃執(zhí)行一條delete語(yǔ)句,把對(duì)象從session緩存中刪除枷莉,該對(duì)象成為刪除狀態(tài)娇昙。
hibernate.use.identifier.rollback屬性,默認(rèn)值為false依沮,若設(shè)置為true涯贞,將改變delete行為,那么會(huì)把對(duì)象的OID置為空危喉,成為臨時(shí)對(duì)象宋渔。
@Test
public void testDelete() {
News news = (News) session.get(News.class, 11);
session.delete(news);
// session.update(news);//刪除狀態(tài)的不可以進(jìn)行update操作。
System.out.println(news);
}
Evict()方法:
@Test
public void testEvict() {
News news1 = (News) session.get(News.class, 9);
News news2 = (News) session.get(News.class, 8);
news1.setTitle("uu");
news2.setTitle("mm");
session.evict(news2);// 從緩存中移除對(duì)象辜限,該對(duì)象成為游離狀態(tài)對(duì)象皇拣。
session.update(news2);// 該對(duì)象若是要update的話,需要顯示的調(diào)用,因?yàn)樵搶?duì)象已經(jīng)屬于游離對(duì)象氧急。
}