Hibernate之session接口(二)

1.對象的幾種狀態(tài)

在所有之前,說明一下,對于hibernate,它的對象有三種狀態(tài),transient、persistent、detached

下邊是常見的翻譯辦法:

transient:瞬時態(tài)或者臨時態(tài)

(new DeptPo(1,”行政部”,20,”行政相關”),該po的實例和session沒有關聯(lián),該po的實例處于transient)

persistent:持久化狀態(tài)

(和數(shù)據(jù)庫中記錄想影射的Po實例,它的狀態(tài)是persistent, 通過get和load等得到的對象都是persistent)

detached:脫管狀態(tài)或者游離態(tài)

(1)當通過get或load方法得到的po對象它們都處于persistent,但如果執(zhí)行delete(po)時(但不能執(zhí)行事務),該 po狀態(tài)就處于detached, (表示和session脫離關聯(lián)),因delete而變成游離態(tài)可以通過save或saveOrUpdate()變成持久態(tài)

(2)當把session關閉時,session緩存中的persistent的po對象也變成detached

因關閉session而變成游離態(tài)的可以通過lock、save、update變成持久態(tài)

持久態(tài)實例可以通過調(diào)用 delete()變成游離狀態(tài)。

通過get()或load()方法得到的實例都是持久化狀態(tài)的。

游離狀態(tài)的實例可以通過調(diào)用lock()或者replicate()進行持久化。

save()和persist()將會引發(fā)SQL的INSERT,delete()會引發(fā)SQLDELETE,

而update()或merge()會引發(fā)SQL UPDATE。對持久化(persistent)實例的修改在刷新提交的時候會被檢測到,它也會引起SQL UPDATE。

saveOrUpdate()或者replicate()會引發(fā)SQLINSERT或者UPDATE

可以通過session提供的方法用于改變對象的狀態(tài)。

save()方法:

1.使一個臨時對象成為持久化對象。

2.為對象分配ID。

3.在 flush緩存的時候發(fā)送一條insert語句。

4.save之前設置的ID是無效的。

5.持久化對象的ID是不可修改的。

@Test

public void testSave() {

News news = new News();

news.setAuthor("wenyu2");

news.setDate(new Date());

news.setTitle("php");

news.setId(23);//該行設置無效

System.out.println(news);

session.save(news);

System.out.println(news);

news.setId(45);//改行拋出異常。

persist()方法:

與save方法類似的是persist()方法, persist()方法也可以執(zhí)行insert操作,但是跟save的區(qū)別是,若在persist之前設置了ID值, 則拋出異常,不會insert操作。

@Test

public void testPersist() {

News news = new News();

news.setAuthor("wangwu");

news.setDate(new Date());

news.setTitle("py");

news.setId(34);//拋異常,不會執(zhí)行insert操作。

session.persist(news);

}

get()方法:該方法會立即查詢加載數(shù)據(jù)庫中的對象(立即執(zhí)行select語句)。但是若是該記錄在數(shù)據(jù)庫中不存在那么返回一個null(沒有即沒有很直接)。

@Test

public void testGet() {

News news = (News) session.get(News.class, 4);

session.close();//若是手動關閉session,下面的打印也會成功。

System.out.println(news);

}

Load()方法:該方法功能和get相同,但是屬于延遲加載的方法。

也就是說,執(zhí)行l(wèi)oad方法之后,若是不使用該對象那么不會執(zhí)行select語句,僅僅返回一個代理對象。與此同時若是查詢的記錄在數(shù)據(jù)庫中不存在,那么會拋出異常(找不到對象),可以理解為返回代理對象之后,該代理對象無法找到與之匹配的真實對象,即拋異常。

若是在使用對象之前手動關閉了session,在使用對象的時候會拋出懶加載異常。而get卻是可以打印出來。

@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)用的時候拋出懶加載異常。

}

update方法:

1.若更新一個持久化對象,不需要顯示的調(diào)用update方法,因為在Transaction 的commit方法之前會先執(zhí)行flush操作(出發(fā)update語句)。

2.當session關閉或者執(zhí)行了evict方法,將對象從session 緩存中移除,那么該對象處于游離狀態(tài),此時需要顯示調(diào)用update()方法,這個update()顯示調(diào)用的時候,不論對象的屬性是否發(fā)生變化都會執(zhí)行update語句,在跟觸發(fā)器協(xié)同工作的時候,為了避免這個問題,我們可以使用在hbm.xml文件中設置select-before-date值為true,檢測是否有改變,若是沒有改變那么不會發(fā)送update語句。(該方式不常用)。

若數(shù)據(jù)表中沒有該記錄,但是還是執(zhí)行update的話,會導致異常。

當update方法關聯(lián)一個游離狀態(tài)的對象時,如果session中已經(jīng)存在相同ID的持久化對象,會拋異常,因為session 中不能存在兩個OID相同的對象。

@Test

public void testUpdate() {

News news = (News) session.get(News.class, 4);

transaction.commit();

session.close();// 至此news對象是一個游離狀態(tài)的。

// news.setId(6);//該行會拋異常,ID在數(shù)據(jù)表中不存在。

session = sessionFactory.openSession();

transaction = session.beginTransaction();

// news.setAuthor("JDBC");// news既不在原來的session緩存中,也不在新的緩存中。

// News news2=(News)session.get(News.class, 5);//

session.update(news);// 也就是需要通過顯示的執(zhí)行update方法,將該對象變?yōu)槌志脿顟B(tài)。

}

saveOrUpdate()方法:

根據(jù)是否有OID 來判斷是采用save操作還是update操作。 若OID不為空但是沒有對應的記錄,會拋異常。

@Test

public void testSaveOrUpdate() {

News news = (News) new News("FF", "ff", new Date());

news.setId(34);//若該ID在數(shù)據(jù)庫中沒有對應的記錄,拋異常。

session.saveOrUpdate(news);

}


delete方法:

可刪除一個游離對象,也可以刪除一個持久化對象。session 的delete方法處理過程:

計劃執(zhí)行一條delete語句,把對象從session緩存中刪除,該對象成為刪除狀態(tài)。

hibernate.use.identifier.rollback屬性,默認值為false,若設置為true,將改變delete行為,那么會把對象的OID置為空,成為臨時對象。

@Test

public void testDelete() {

News news = (News) session.get(News.class, 11);

session.delete(news);

// session.update(news);//刪除狀態(tài)的不可以進行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);// 從緩存中移除對象,該對象成為游離狀態(tài)對象。

session.update(news2);// 該對象若是要update的話,需要顯示的調(diào)用,因為該對象已經(jīng)屬于游離對象。

}

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容