持久化对象的生命周期有三种,分别是瞬时态(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就是出于瞬时态的持久化对象。
通过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();
在调用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("北京");
虽然后来又修改了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();
当使用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();
至此Hibernate中持久化对象的三种状态介绍完了。我们会发现处于瞬时态和脱管态的对象不在Hibernate的Session管理中,这时无论怎样修改对象的属性都不会影响数据库中的数据。而处于持久态的对象在Session对象执行close()方法或Transaction对象执行commit()方法时,数据库中数据会同步更新,这也是Hibernate对对象的“脏”数据进行检查的一种方式。
本文系作者的个人理解,欢迎交流。