程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> Hibernate開發實踐筆記--對象在set屬性時更新了數據庫問題

Hibernate開發實踐筆記--對象在set屬性時更新了數據庫問題

編輯:MySQL綜合教程

Hibernate開發實踐筆記--對象在set屬性時更新了數據庫問題


之前一直沒發現這個問題,後來是因為我的導航欄數據庫中數據發生變動後,產生菜單的時候又update了一遍數據庫中的數據,使得部分數據值為空了,當時覺得很奇怪,後來仔細看了下log4j打印的日志發現其中有更新的動作,在代碼中將數據庫中獲取到的對象set一個對象屬性時,數據庫就update了,但是這個問題是怎麼產生的呢?

問題重述

Set users = new HashSet();
User user = null;
for(int i = 0; i < 10; i++){
	user = new User();
	user.setUserName("wy" + i);
	users.add(user);
}
Company company = userDao.getCompany();
company.setUsers(users);

類似上面的代碼,company是剛剛從數據庫中獲取到的,然後我構造了一個User對象的Set集合,然後在這裡直接setUsers的時候就出現了更新數據庫的動作,當然這段代碼只是示例並不是實際的項目代碼。

問題在哪裡

Hibernate分為三種基本的狀態:游離態、自由態(臨時狀態)、持久態。 持久化狀態:與session關聯並且和在數據庫有數據,已經持久化了並且在數據庫的緩存當中了。 我這裡的這個對象應該是持久化狀態的對象然後我直接構造了一個user對象的set集合,同時對這個對象進行set操作,那麼緩存Session中的數據發生改變,那麼接著數據庫也會跟著進行相應的改變。所以就執行了update的更新操作。

怎麼解決

其他兩種狀態: 1. 臨時狀態:就是直接new出來的對象,既沒有持久化到數據庫中去,也沒有在session當中。 2. 游離狀態:在Session中沒有了,但是已經持久化到了數據庫當中。 那麼這個地方怎麼解決呢? 1.如果這個對象(例子中的company)本身不需要用的話,可以直接new一個Company的對象出來然後再setUsers這個時候因為不是Session中的數據,那麼不會因為對象的屬性發生改變而同步到數據庫中去。 2. 如果這個對象(例子中的company)要用的到,那麼,在set之前可以先將其轉為游離態,這樣的話會用到session的幾個方法:close、clear、evict。 close方法:關閉session這樣這個對象肯定是游離態了,因為session已經關閉了,但是往往我們實際的開發過程中,session在後面是要用的到的,所以這個方法可行,但是不一定用得上,分清具體的情況。 clear方法:將session中的所有的對象全部清除出緩存,這個方式有點勞師動眾,不過session清除了全部的對象之後自然就會變為游離態了,這樣做不是很好吧我感覺。 evict方法:將某一個對象清除出緩存session,這個方法是很好的實現方式,推薦使用。調用的時候是這樣的,session.evict(Object obj);這樣就可以了。

知識擴充:深入理解Hibernate三種狀態

狀態之間如何轉換

\
1. Save和Update:save的時候是將自由態的對象持久化到數據庫中,而update的時候一般是將游離態的對象持久化到數據庫中去。
2. update、saveOrUpdate、merge:saveOrUpdate的作用是當Session中存在要操作的對象的時候,拋出異常信息,當不存在的時候,如果這個對象沒有持久化標識屬性,那麼將這個對象save,如果這個對象有持久化標識屬性的話,那麼直接update就可以了。對於單純的update來說,程序會在一個Session中加載對象,然後將這個對象關閉,然後這個對象發生變化之後,再update的時候就會打開另一個Session將對象持久化到數據庫中去。merge的話是當Session中存在要操作的對象的時候,不會拋出異常而是直接將這個對象的數據拷貝到Session中持久態的對象中去,這樣對象還是維持著原來的狀態。
3.persist和save:都是用來保存臨時對象到數據庫的,但是persist並不保證對象的主鍵立即被創建好,有可能推遲到flush的時候。但是save的時候會立即創建好的,所以save的時候一般可以通過對象拿到主鍵值。
4. flush和update:update的時候對象多是游離態的對象,也就是說數據庫中已經存在了,但是並不在Session中的對象通過update會更新到數據庫當中去。而flush是將本來持久態的數據更新到數據庫中去。
5. lock是將一個沒有更改過的托管的對象轉為持久態的對象,但是他不能針對那些delete後的托管的對象。

代碼實例分析

User user = new User();
user.setName("wy");
//目前還是一個臨時對象

Session session = sessionFactory.openSession();
Tansaction tx = session.beginTansaction();
//目前還是一個臨時對象
session.save(user);
//user處於持久態了
tx.commit();
session.close();// 游離態了

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved