1状态转换图。
2 三种状态
2.1 临时状态(transient)
刚刚new创建的对象,还未与session关联。
2.2 持久化状态(persistent)
已经被持久化,加到了session的缓存中。
以下操作会使对象转换到持久化状态:
1)get()或者load()等查询操作。
2)临时状态执行save()或者saveOrUpdate()操作。
3)游离状态执行update()或者saveOrUpdate()操作。
session.save(course);
course.setName("dddd");
course.setName("ttt");
session.save(course);//或者注释掉
course.setName("ddddddd");
session.update(course);//或者注释掉
以上效果是一样的,处于持久化状态的对象只会执行一次update SQL语句,根据最后一个setName()方法,因为持久化对象是在清理缓存的时候生成SQL的,如果setName的值跟之前的值一样则不生成update SQL, session负责根据持久化对象的状态变化来同步数据库。什么时候清理缓存,请参见笔者另一篇博客:Hibernate Session缓存
http://frank1234.iteye.com/blog/2174119 。
处于持久化状态的对象不需要调用session.save()和session.update()
执行commit()后仍处于持久化状态。
例如:
session.save(course);
tx.commit();
tx.begin();
course.setName("xxxx");
session.save(course); //仍然生成的是update SQL语句
tx.commit();
2.3游离状态(detached)
已经被持久化,但不处于session的缓存中,在数据库中存在对应的记录。
调用close() evict() clear()会使对象从持久化状态变为游离状态。
evict()使一个确定的对象处于游离状态,clear()是使所有的对象处于游离状态。
evict()什么场景下使用呢?
1)不希望按照该对象的状态变化来同步更新数据库。
2)批量更新或者批量删除时,当更新或者删除一个对象后,及时释放该对象占用的内存。但是这种类型的操作更建议直接使用JDBC API操作。
通常不提倡使用evict()和clear()。
evict()以后再重新load,将是两个不同的对象。
Course course16 = (Course)session.load(Course.class, 16);
session.evict(course16);
Course course17 = (Course)session.load(Course.class, 16);
System.out.println(course16 == course17);//输出false
那么直接new 一个数据库中存在的对象,应该属于什么状态呢?
例如:Course course = new Course();
course.setId(1); //数据库中存在id=1的记录
course.setName("frank1234");
执行session.save(course),会插入一条新的记录。
执行session.update(course),执行update语句。
Course course = (Course)session.get(Course.class,16);
session.evict(course);
session.save(course);//也会新插入一条记录,之前直接new的对象跟这个操作结果一样。
所以感觉只要是跟数据库中有对应记录的,即使通过new 创建的也属于游离态对象范畴,不知道自己理解的对不对。
《精通Hibernate》 -孙卫琴