在Hibernate中,持久化對象在被操作過程中可以分爲三個時期,這三個時期是和Session的週期相關的,因爲Hibernate中的操作都是基於Session完成的。所以Session對象的生命週期也關係着持久化對象的生命週期。
持久化對象的生命週期有三種,分別是瞬時態(Transient),持久態(Persistent)和脫管態(Detached)。
瞬時態的對象是剛剛用new關鍵字創建出來的,還沒有進入Session,此時的對象沒有和數據庫中的記錄對應。示例代碼如下:
- User user = new User();
- user.setName("Sarin");
- user.setCity("大連");
- user.setDepartment("研發部");
- user.setPhone("15912345678");
- user.setHireTime(new java.util.Date());
User user = new User();
user.setName("Sarin");
user.setCity("大連");
user.setDepartment("研發部");
user.setPhone("15912345678");
user.setHireTime(new java.util.Date());
這時user就是出於瞬時態的持久化對象。
通過Session對象的save(),persist()或者saveOrUpdate()方法進行保存處於瞬時態的對象後,該對象就變爲持久態。此時Session中已經存在該對象,並且對應數據庫中的一條記錄。值得注意的是在Session對象失效之前,對持久態對象的任何修改,在調用Session對象的close()方法或者Transaction對象的commit()方法之後,數據庫表中對應的數據會同時更新。示例代碼如下:
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.getCurrentSession();
- Transaction tx = session.beginTransaction();
- User user = new User();
- user.setName("Sarin");
- user.setCity("大連");
- user.setDepartment("研發部");
- user.setPhone("15912345678");
- user.setHireTime(new java.util.Date());
- session.save(user);
- tx.commit();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
User user = new User();
user.setName("Sarin");
user.setCity("大連");
user.setDepartment("研發部");
user.setPhone("15912345678");
user.setHireTime(new java.util.Date());
session.save(user);
tx.commit();
在調用save()方法後,持久化對象user就變爲持久態,但是執行了commit()方法之後,數據庫操作纔會進行,這點必須明確。所以在數據庫操作執行之前對持久化對象的修改Hibernate可以感知。
而且Session對象的get()和load()方法也可以返回一個持久態的對象,這個對象代表數據庫表中的一條記錄。
脫管態,這個要格外注意,不是託管態,是離開Session管理的狀態。處於脫管態的持久化對象的標識符屬性和數據庫表中某條記錄的主鍵對應,但是它脫離了Session的管理,再次對其操作時,Hibernate無法感知其變化。如下示例:
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.getCurrentSession();
- Transaction tx = session.beginTransaction();
- User user = new User();
- user.setName("Sarin");
- user.setCity("大連");
- user.setDepartment("研發部");
- user.setPhone("15912345678");
- user.setHireTime(new java.util.Date());
- session.save(user);
- tx.commit();
- user.setCity("北京");
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
User user = new User();
user.setName("Sarin");
user.setCity("大連");
user.setDepartment("研發部");
user.setPhone("15912345678");
user.setHireTime(new java.util.Date());
session.save(user);
tx.commit();
user.setCity("北京");
雖然後來又修改了user對象的city屬性,但是是在脫管態修改的,程序結束也不能再影響數據庫中數據變化。處於脫管態的對象可以重新調用Session對象的update()方法回到持久態,否則Java虛擬機會在適當時間進行垃圾收集。重新持久化對象的過程如下:
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.getCurrentSession();
- Transaction tx = session.beginTransaction();
- User user = new User();
- user.setName("Sarin");
- user.setCity("大連");
- user.setDepartment("研發部");
- user.setPhone("15912345678");
- user.setHireTime(new java.util.Date());
- session.save(user);
- tx.commit();
- user.setCity("北京");
- session = sessionFactory.getCurrentSession();
- tx = session.beginTransaction();
- session.update(user);
- tx.commit();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
User user = new User();
user.setName("Sarin");
user.setCity("大連");
user.setDepartment("研發部");
user.setPhone("15912345678");
user.setHireTime(new java.util.Date());
session.save(user);
tx.commit();
user.setCity("北京");
session = sessionFactory.getCurrentSession();
tx = session.beginTransaction();
session.update(user);
tx.commit();
當使用Session對象的delete()方法刪除數據後,處於持久態的對象失去和數據庫數據的對應關係,此時的持久化對象將在適當時間被Java虛擬機進行垃圾收集。
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.getCurrentSession();
- Transaction tx = session.beginTransaction();
- User user = (User) session.get(User.class, new Integer(1));
- session.delete(user);
- tx.commit();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
User user = (User) session.get(User.class, new Integer(1));
session.delete(user);
tx.commit();
至此Hibernate中持久化對象的三種狀態介紹完了。我們會發現處於瞬時態和脫管態的對象不在Hibernate的Session管理中,這時無論怎樣修改對象的屬性都不會影響數據庫中的數據。而處於持久態的對象在Session對象執行close()方法或Transaction對象執行commit()方法時,數據庫中數據會同步更新,這也是Hibernate對對象的“髒”數據進行檢查的一種方式。
本文系作者的個人理解,歡迎交流。