在面向对象的开发中,程序的运行都是通过对象的方式对数据库进行增删改查的操作,必然在持久化过程中产生一些列的对象,比如登陆,必然会有实例化的UserEntity对象,从数据库Select出来的对象,Save到数据库的对象,如何区分这些对象以及当前会话的状态,下面看NHibernate中的对象状态的管理:
Nhibernate在持久化对象的生命周期,将对象分为三个状态:
也叫临时态,顾名思义,对象是临时创建的,即刚实例化的对象:
UserEntityenUser = new UserEntity();
这个enUser对象现在就处于瞬时态,因为此时只是给enUser对象分配了一块内存空间,还没有进入Nhibernate的Session缓存,更没有持久化到数据库。
瞬时对象特点:
对象在数据库没有记录,也不和Session关联。
瞬时对象被保存到数据库或者从数据库查询来的对象,并且还在Session管理中的对象。
瞬时对象转化为持久对象:(1)通过Session的Save()和SaveOrUpdate()方法将瞬时对象持久化到数据库,(2)通过Get(),Load()等查询方法查询到数据对象。
持久化对象的特点:
对象与数据库中记录同步,并且数据变更处于Session的管理之下。
由持久态转换而来,在与持久化对象关联的Session被关闭后,对象就变成游离态,但是还拥有持久化对象的所有属性。
游离对象的特点:
和瞬时对象一样,都没有处于Session关联。不同的是游离对象是经过持久化的对象,在数据库中有记录。
以上简单的介绍了Nhibernate持久化的三个状态,在持久化对象的生命周期内,这三个状态并不是孤立的,它们之间存在的相互转换的过程:
状态分析:
//瞬时态对象
UserEntity enUser = new UserEntity();
enUser.name = "yiming";
//关联Session,调用Save(enUser)持久化到数据库,状态变为持久态,但是还没有更新到数据库,需要在进行flush()。
Session.Save(enUser);
enUser.name = "liuming";
Session.Save(enUser); //无效
//将session的缓存中的数据与数据库同步,关闭Session
Session.Flush();
说明:当执行持久化操作时,持久化操作并没有立即执行(更新到数据库),而是被记录下来,直到Session.Flush时才会实际更新到数据库,这样做的原因很容易理解,就是为了避免频烦的数据库连接操作。如果没有调用Flush而关闭了会话,当前会话中的持久对象将不会持久化!并且对已经持久化的对象调用Save()或者Update()是没有意义的。
持久态转换成游离态就是一个清理Session的过程,通常不会手动去调用evict(),close(),clear()这些图中列出的方法,而是由Nhibernate去管理,清理的时机:
1、commit() 方法被调用时。
2、查询时会主动commit清理缓存,保证查询结果能反映对象的最新状态。
3、调用session.flush()方法。
以update()方法为例:
Session.Update(enUser);
如果enUser是持久化对象,那么不进行任何操作,即可以同步到数据库。如果enUser是游离对象,那么就必须先转为持久对象,然后再同步到数据库。所以Update的时候也会发出select语句。
其他的方法不再一一说明,其实只要明白了这三种状态以及转换过程,结合我们以前通过sql语句的实现(因为Nhibernate的这些方法最终还是通过sql语句去操作数据库的)的经验去考虑,就很容易理解。
一个月的开发,在投诉系统中遇到最多的问题就是调用底层Save,Update,SaveOrUpdate方法,以及在级联操作的过程中的问题,由于对这三个状态的不了解,错误不断,完全是一个方法一个方法的尝试,也摸索到了一些规律,再加上这次的学习对Nhibernate的三态更清晰了。
本文也一直在出现一个词Session,这个词都不陌生,但Nhibernate的Session是我们之前用到Session吗,在Nhibernate中的作用是什么,带着问题进入下一篇(NHibernate 缓存机制)