Hibernate學習筆記(三)Session

Hibernate在對數據庫進行操作之前,必須先取得Session實例,相當於JDBC在對數據庫操作之前,必須先取得Connection實例, Session是Hibernate操作的基礎,它不是設計爲線程安全(Thread-safe),一個Session由一個線程來使用。

  • 開啓Session

Session實例由SessionFactory開啓獲得,例如:

Configurationconfig = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
....
tx.commit();
session.close();


開啓Session不會馬上取得Connection,而是在最後真正需要連接數據庫進行更新或查詢時纔會取 得Connection,如果有設定Connection pool,則從Connection pool中取得Connection,而關閉Session時,如果有設定Connection pool,則是將Connection歸還給Connection pool,而不是直接關閉Connection。

在Hibernate中,開啓一個Session會建立一個Persistencecontext,它可以進行快取管理、dirty check等,而所有的讀取、更新、插入等動作,則是在Transaction中完成。

  • 儲存數據

透過Session,可以對數據庫進行新增、刪除、更新,例如使用save()新增一筆數據:

User user = newUser(); 
user.setName("momor"); 
user.setAge(new Integer(26));

Session session = sessionFactory.openSession();
Transaction tx =session.beginTransaction();
session.save(user); 
tx.commit();
session.close();


save()之後,不會馬上對數據庫進行更新,而是在Transaction的commit()之後纔會對數據庫進行更新,在Transaction之間 的操作要就全部成功,要就全部失敗,如果更新失敗,則在數據庫層面會撤消所有更新操作,然而內存中的持久對象是不會回覆原有狀態的,事實上,當 Transaction失敗,這一次的Session就要馬上跟着失效,放棄所有內存中的對象,而不是嘗試以原對象再進行更新的動作。

  • 取得資料

您使用get()或load()方法取得id爲1的數據:

Session session =sessionFactory.openSession();
Transaction tx =session.beginTransaction();

User user = (User)session.get(User.class, new Integer(1));
tx.commit();
session.close();


如果未能發現相符合的數據,則get()方法會返回null,而load()方 法會丟出ObjectNotFoundException,在進階的應用中,load()方法可以返回代理(proxy)對象,在必要時才真正查詢數據庫取得對應數據,並可充分利用快取機制。

在Hibernate 3中,取消了find()方法,您必須透過Query或Criteria來進行數據查詢。

  • 刪除數據

接下來看看使用Session刪除數據,可使用delete()刪除數據:

Session session =sessionFactory.openSession();
Transaction tx =session.beginTransaction();
User user = (User)session.get(User.class, new Integer(1));
session.delete(user);
tx.commit();
session.close();

  • 更新數據

當您在同一個Session中取出數據並封裝爲Persistence Object,接着更新對象狀態,而後將Transaction commit,則對象上的狀態更新將反應至數據庫中,您無需額外進行任何的更新操作。

如果您開啓了一個Session,從數據表中取出數據顯示到用戶接口上,之後關閉Session,當用戶在接口上操作完畢並按下儲存時,這時您要重新 開啓一個Session,使用update()方法將對象中的數據更新至對應的數據表中:

Session session =sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = (User)session.get(User.class, new Integer(2));
tx.commit();
session.close();
....
user.setAge(new Integer(27));
session = sessionFactory.openSession();    
tx= session.beginTransaction(); 
session.update(user);
tx.commit();
session.close();



Session提供了一個saveOrUpdate()方法,爲數據的儲存或更新提供了一個統一的操作接口,藉由定義映像文件時,設定< id>標籤的unsaved-value來決定什麼是新的值必需,什麼是已有的值必須更新: 

<idname="id" column="id"type="java.lang.Integer" unsaved-value="null">
    <generator class="native"/> 
</id> 


unsaved-value可以設定的值包括: 

·        any:總是儲存

·        none:總是更新

·        null:id爲null時儲存(預設)

·        valid:id爲null或是指定值時儲存


這樣設定之後,您可以使用Session的saveOrUpdate()方法來取代update()方法。

  • 合併狀態

以這邊的例子來說:

Session session =sessionFactory.openSession();
Transaction tx =session.beginTransaction();
User user1 =(User) session.get(User.class, new Integer(2));
tx.commit();
session.close();
....
user1.setAge(newInteger(27));

session =sessionFactory.openSession();    
tx=session.beginTransaction(); 
User user2 = (User)session.get(User.class, new Integer(2)); // 同一個id
// user1 == user2 爲 false
session.update(user1); // 丟出NonUniqueObjectException
tx.commit();
session.close();



在進行update()之前,您就先從數據庫中取得另一筆 資料,之後再嘗試更新user1,由於目前的Persistence context已加載一筆資料,並有同一個id的User 實例了,同一個Persistencecontext不會有兩個相同id的對象實例,因此丟出NonUniqueObjectException。

就這邊的例子來說,您應該使用merge()而不是update():

Session session =sessionFactory.openSession();
Transaction tx =session.beginTransaction();
User user1 =(User) session.get(User.class, new Integer(2));
tx.commit();
session.close();
....
user1.setAge(newInteger(27));

session =sessionFactory.openSession();    
tx=session.beginTransaction(); 
User user2 = (User)session.get(User.class, new Integer(2)); // 同一個id
User user3 =(User) session.merge(user1);
// user1 == user2 爲 false
// user2 == user3 爲 true
tx.commit();
session.close();


merge()會將user1與user2的狀態合併,傳回的對象實例就是user2原先所參考的實例。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章