Hibernate中对数据的操作是以其三种状态为前提的,这三种状态transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),大家也许都知道三者之间的区别:瞬时状态的对象就是New出来的对象,尚未保存到数据库中,数据库没有对应的记录;持久化状态就是已经被保存到数据库中,并且已经被Session管理;离线状态就是数据库中有,但是Session中没有,不被Session管理。下面我们通过一张图和些具体的实例来学习一下Hibernate中的三态。至于为什么要划分这三种状态,其实我的感觉:之所以划分这三种状态,就是为了让我们了解在什么时候用什么方法,别云里雾里的乱用。
session = HibernateUtil.openSession(); session.beginTransaction(); //此时,刚new出来的user对象是瞬时状态,不被session管理,所以不能进行update,delete,evict,close等操作 User user = new User(); user.setUsername("admin"); user.setPassword("admin"); user.setBorn(new Date()); session.save(user); session.getTransaction().commit();
以上user就是一个Transient(瞬时状态),在执行session.save(user)执行之前,user并没有被session进行托管,即在session的缓存中还不存在user这个对象,当执行完save方法后,此时user被session托管,并且数据库中存在了该对象user就变成了一个Persistent(持久化对象)。之后,Hibernate向数据库发出一条insert语句
Hibernate: insert into t_user (born, password, username) values (?, ?, ?)
这样,对象就会被session管理,并且在数据库中也存在了相对应的一条记录,该对象转变为持久化状态。
session = HibernateUtil.openSession(); session.beginTransaction(); User user = new User(); user.setUsername("admin"); user.setPassword("admin"); user.setBorn(new Date()); //以上部分的user处于瞬时状态 //执行save之后,user转变为持久化状态 session.save(user); //此时u是持久化状态,已经被session所管理,当在提交时,会把session中的对象和目前的对象进行比较 //如果两个对象中的值不一致就会继续发出相应的sql语句 user.setPassword("creator"); //此时会发出2条sql,一条用户做插入,一条用来做更新 session.getTransaction().commit();
Hibernate: insert into t_user (born, password, username) values (?, ?, ?) Hibernate: update t_user set born=?, password=?, username=? where id=?
session = HibernateUtil.openSession(); session.beginTransaction(); User u = new User(); u.setUsername("test1"); u.setPassword("test1"); session.save(u); u.setPassword("test2"); //下面一条语句没有意义 session.save(u); u.setPassword("test2"); //下面一条语句没有意义 session.update(u); session.getTransaction().commit();
Hibernate: insert into t_user (born, password, username) values (?, ?, ?) Hibernate: update t_user set password=?, username=? where id=?
(1)我们来分析一下session.save(u)方法执行之前,u是一个瞬时状态,当save(u)方法执行完之后,成为了一个持久化对象;会执行一条insert语句(2)之后u.setPassword("test2"),session检查自身管理的Password,不是test2,这里会标记一下更新操作(没有执行,只是标记),所以session.save(u)是没有任何意义的。(3)往下继续执行 u.setPassword("test2");这里也会标记一下有一个更新操作,但是同样的也没有执行update语句,所以 session.update(u); 也是没有意义的(4)只有到了session.getTransaction().commit();会向数据库统一发一条更新语句,实现数据的更新。
1、游离态→持久态
执行Update或者saveOrUpdate方法,会将数据库的数据纳入到session中管理,从而将游离态的数据,转换为持久态的数据。
session.beginTransaction(); User u = new User(); u.setId(1); //完成update之后也会变成持久化状态 session.update(u); u.setPassword("test"); u.setUsername("test"); //会发出一条sql session.update(u); session.getTransaction().commit();
Hibernate: update t_user set password=?, username=? where id=?
2、游离态→瞬时态
session = HibernateUtil.openSession(); session.beginTransaction(); User u = new User(); u.setId(1); //现在u就是transient对象 session.delete(u); //此时u已经是瞬时对象,不会被session和数据库所管理 u.setPassword("admin"); session.getTransaction().commit();
Hibernate: delete from t_user where id=?
我们再回头看那张图片,理解一下Hibernate的三种状态。
瞬时状态:刚new出来的对象,不被Session管理,数据库中也不存在,可以进行的操作:save,saveorupdate,从而转变为持久态。
持久状态:被session管理,且数据库中也存在的对象。执行evict,close,clear会变为游离状态,执行delete会变成临时状态,当然,自身也可以进行对应的增删改查操作。
游离状态:数据库中有,但是session中没有。执行update,saveorupdate,lock会变成持久化状态,放入session中管理,执行delete会转化成临时状态。