Hibernate 中的三种状态
瞬时状态:刚创建的对象还没有被 Session 持久化、缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有 OID。
持久状态:对象经过 Session 持久化操作,缓存中存在这个对象的数据为持久状态并且数据库中存在这个对象对应的数据为持久状态这个时候有 OID。
游离状态:当 Session 关闭,缓存中不存在这个对象数据而数据库中有这个对象的数据并且有 OID 为游离状态。
注:OID 为了在系统中能够找到所需对象,我们需要为每一个对象分配一个唯一的表示号。在关系数据库中我们称之为关键字,而在对象术语中,则叫做对象标识
(Object identifier-OID).通常OID在内部都使用一个或多个大整数表示,而在应用程序中则提供一个完整的类为其他类提供获取、操作。
Hibernate 数据状态图:
需要注意的是:
当对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用 save() 或 update() 方法是没有意义的。
1 | Student stu = new Strudnet(); |
执行 sql:
1 | Hibernate: insert into t_user (born, password, username) values (?, ?, ?) |
6.
1 | session = HibernateUtil.openSession(); |
7.
1 | session = HibernateUtil.openSession(); |
如果此时我将u.setId(4)这句话注释掉,那么此时u就是一个瞬时的对象,那么此时就会执行save操作,就会发送一条insert语句
1 | Hibernate: insert into t_user (born, password, username) values (?, ?, ?) |
12.
session = HibernateUtil.openSession();
session.beginTransaction();
User u1 = (User)session.load(User.class, 3);
System.out.println(u1.getUsername());
User u2 = new User();
u2.setId(3);
u2.setPassword("123456789");
session.saveOrUpdate(u2);
我们再来看一下这个例子,此时我们的u1已经是持久化的对象了,保存在session缓存中,u2通过调用saveOrUpdate方法后也变成了一个持久化的对象,此时也会保存在session缓存中,这个时候session缓存中就存在了一个持久化对象有两个引用拷贝了,这个时候hibernate就会报错
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.xiaoluo.bean.User#3]
一个session中不能存在对一个持久化对象的双重copy的,要解决这个方法,我们这里又要介绍session的另一个方法 merge方法,这个方法的作用就是解决一个持久化对象两分拷贝的问题,这个方法会将两个对象合并在一起成为一个对象。
session = HibernateUtil.openSession();
session.beginTransaction();
User u1 = (User)session.load(User.class, 3);
System.out.println(u1.getUsername());
User u2 = new User();
u2.setId(3);
u2.setPassword("123456789");
session.merge(u2);
session.getTransaction().commit();
我们看到通过调用了merge方法以后,此时会将session中的两个持久化对象合并为一个对象,但是merge方法不建议被使用
Hibernate: select user0_.id as id0_0_, user0_.born as born0_0_, user0_.password as password0_0_, user0_.username as username0_0_ from t_user user0_ where user0_.id=?
zhangsan
Hibernate: update t_user set born=?, password=?, username=? where id=?
总结:
①.对于刚创建的一个对象,如果session中和数据库中都不存在该对象,那么该对象就是瞬时对象(Transient)。
②.瞬时对象调用save方法,或者离线对象调用update方法可以使该对象变成持久化对象,如果对象是持久化对象时,那么对该对象的任何修改,都会在提交事务时才会与之进行比较,如果不同,则发送一条update语句,否则就不会发送语句。
③.离线对象就是,数据库存在该对象,但是该对象又没有被session所托管。
参考:
如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理