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原先所參考的實例。