01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态
以下属于不明来源资料:
引入
在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象。这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根据对象和当前会话的关联状态,我们可以把对象分为三种:
瞬时对象:对象刚刚建立。该对象在数据库中没有记录,也不在ISession缓存中。如果该对象是自动生成主键,则该对象的对象标识符为空。
持久化对象:对象已经通过NHibernate进行了持久化,数据库中已经存在对应的记录。如果该对象是自动生成主键,则该对象的对象标识符已被赋值。
托管对象:该对象是经过NHibernate保存过或者从数据库中取出的,但是与之关联的ISession已经关闭。虽然它有对象标识符且数据库中存在对应记录,但是已经不再被NHibernate管理。
对象状态
NHibernate提供了对象状态管理的功能,支持三种对象状态:瞬时态(Transient)、持久态(Persistent)、托管态(Detached)。
1.瞬时态(Transient)
对象刚刚创建,还没有来及和ISession关联的状态。这时瞬时对象不会被持久化到数据库中,也不会被赋上标识符。如果不使用则被GC销毁。ISession接口可以将其转换为持久状态。
这像这样,刚刚创建了一个Customer对象,是一个瞬时态对象:
var customer = new Customer() { Firstname = "zhang", Lastname = "san" };
2.持久态(Persistent)
刚被保存的或刚从数据库中加载的。对象仅在相关联的ISession生命周期内有效,在数据库中有相应记录并有标识符。对象实例由NHibernate框架管理,如果有任何改动,在当然操作提交时,与数据库同步,即将对象保存更新到数据库中。
3.托管态(Detached)
持久对象关联的ISession关闭后,这个对象在ISession中脱离了关系,就是托管态了,托管对象仍然有持久对象的所有属性,对托管对象的引用仍然有效的,我们可以继续修改它。如果把这个对象重新关联到ISession上,则再次转变为持久态,在托管时期的修改会被持久化到数据库中。
对象状态转换
在同步数据库的情况下执行下面的语句可以转换对象的状态。
测试验证对象
ISession.Contains(object):检查ISession中是否包含指定实例
重新设置ISession
private void ResetSession()
{
if (_session.IsOpen)
_session.Close();
_session = _sessionManager.GetSession();
_transaction.Session = _session;
}
1.瞬时态转换持久态
方法一:ISession.Save():保存指定实例。
[Test]
public void TransientConvertPersistentTest()
{
//瞬时态对象
var customer = new Customer() { Firstname = "zhang", Lastname = "san" };
Assert.IsFalse(_session.Contains(customer));
//仍然是瞬时态,CustomerId属性值为空
//关联ISession保存到数据库中
_session.Save(customer);
//变为持久态,由于表中CustomerId字段自动增长的,保存数据库,CustomerId字段自动加一
//经过NHibernate类型转换后返回CustomerId属性值,保证数据库与实例对象同步
Assert.IsTrue(_session.Contains(customer));
}
方法二:ISession.SaveOrUpdate():分配新标识保存瞬时态对象。
2.持久态转换托管态
方法一:ISession.Evict(object):从当前ISession中删除指定实例
[Test]
public void PersistentConvertDetachedEvictTest()
{
Customer customer = _transaction.GetCustomerById(1);
Assert.IsTrue(_session.Contains(customer));
_session.Evict(customer);
Assert.IsFalse(_session.Contains(customer));
}
方法二:ISession.Close():关闭当前ISession
[Test]
public void PersistentConvertDetachedCloseTest()
{
Customer customer = _transaction.GetCustomerById(1);
Assert.IsTrue(_session.Contains(customer));
ResetSession();
Assert.IsFalse(_session.Contains(customer));
}
3.托管态转换持久态
方法一:ISession.Update():更新指定实例。
[Test]
public void DetachedConvertPersistentUpdateTest()
{
Customer customer = _transaction.GetCustomerById(1);
//持久态对象
Assert.IsTrue(_session.Contains(customer));
//重新设置ISession
ResetSession();
Assert.IsFalse(_session.Contains(customer));
//托管态对象
//在托管态下可继续被修改
customer.Firstname += "CnBlogs";
_transaction.UpdateCustomerTransaction(customer);
//转变为持久态对象
Assert.IsTrue(_session.Contains(customer));
}
看看这个例子:在托管时期的修改会被持久化到数据库中;
注意:NHibernate如何知道重新关联的对象是不是“脏的(修改过的)”?如果是新的ISession,ISession就不能与对象初值来比较这个对象是不是“脏的”,我们在映射文件中定义<id>元素和<version>元素的unsaved-value属性,NHibernate就可以自己判断了。
[Test]
public void DetachedConvertPersistentUpdateAllTest()
{
Customer customer = _transaction.GetCustomerById(1);
//持久态对象
customer.Firstname += "zhang";
Assert.IsTrue(_session.Contains(customer));
//重新设置ISession
ResetSession();
Assert.IsFalse(_session.Contains(customer));
//托管态对象
//在托管态下可继续被修改
customer.Firstname += "CnBlogs";
//这时一起更新
_transaction.UpdateCustomerTransaction(customer);
//转变为持久态对象
Assert.IsTrue(_session.Contains(customer));
}
现在我们初步知道了对象的状态。虽然对象的状态的细节由NHibernate自己维护,但是对象状态在NHibernate应用中还是比较重要的。同时对象状态也涉及了NHibernate缓存、离线查询等内容。
01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态的更多相关文章
- 01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存
一.准备工作 [1]根据操作系统(位数)选择下载相应版本的MemCache, MemCache的下载和安装,参看: http://www.cnblogs.com/easy5weikai/p/37606 ...
- 01-03-02-2【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作-Save方法的一些问题
此文由于当时不知道NHibernate的Sava方法不是更新操作,不知道Save就是Add,造成如下荒唐的求证过程,但结论是对的 ,可报废此文,特此声明. NHibernate--Save方法: Cu ...
- 01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
Nhibernate 并发控制 [1]悲观并发控制 正在使用数据的操作,加上锁,使用完后解锁释放资源. 使用场景:数据竞争激烈,锁的成本低于回滚事务的成本 缺点:阻塞,可能死锁 [2]乐观并发控制: ...
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理
http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 管理NHibernate二级缓存 NHibernate二级缓存由ISessionF ...
- 01-08-04【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之命名缓存
http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 可以在映射文件中定义命名查询,<query>元素提供了很多属性,可以用 ...
- 01-08-02【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider
第一步骤:hibernate.cfg.xml文件补上如下配置: <?xml version="1.0" encoding="utf-8"?> < ...
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结 ...
- 01-06-01【Nhibernate (版本3.3.1.4000) 出入江湖】事务
Nhibernate事务的使用: public void Add(Customer customer) { ISession session = _sessionManager.GetSession( ...
- 01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询
相关资料: http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html 问题的提出: 1.延迟加载,可能会引起session已经关闭的异常,例 ...
随机推荐
- Mapper映射器
在两个独立的对象之间建立通信的对象 需要在两个必须相互隔离的子系统间建立通信. 可能是因为无法修改已有的子系统,或者不愿意在两者之间建立依赖关系.甚至不愿意这两个子系统与另一个部件间建立依赖关系. 运 ...
- js中的继承1--类继承
继承:function Animal(name){ this.name = name; this.showName = function(){ alert(this.name); } } functi ...
- Fedora 19 配置参考
1. 安装完Fedora 19之后,第一件事不是升级系统,而是添加源. 下载我配置好的源,非常全面,适用Fedora 19 x86_64.点我下载 打开终端,切换到repo.zip所在目录:mv re ...
- Python's Exception 层级结构
BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- StopIteration ...
- 【风马一族_git_github】使用Github搭建个人网站
个人网站 访问 https://用户名.github.io ( 风马一族的Github网站 ) 搭建步骤 1)创建个人站点-->新建仓库(注:仓库名必须是[用户名.github.io]) 2) ...
- 《使用shell位置变量进行目录文件的备份小脚本》
今天才发现原来位置变量也可以玩的这么爽!! 这是使用位置变量进行文件目录备份:#!/bin/bashDATE=`date +%F` //日期以年月日输出tar czf $1.$DATE.tar.gz ...
- hadoop2.2.0伪分布式搭建
1.准备Linux环境 1.0点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet ...
- 【Qt】Qt之自定义界面(窗体缩放-跨平台终极版)【转】
简述 通过上一节内容,我们实现了窗体的缩放,功能很不错,但是很遗憾-不支持跨平台!如果对于多平台来说,这是一个硬伤,所以,我们急需要一个能够支持跨平台的实现方案. 在网上看到过很多不同的实现方式,多多 ...
- JS判断鼠标从什么方向进入一个容器
偶然将想到的一个如何判断鼠标从哪个方向进入一个容器的问题.首先想到的是给容器的四个边添加几个块,然后看鼠标进入的时候哪个块先监听到鼠标事件.不过这样麻烦太多了.google了一下找到了一个不错的解决方 ...
- 【转】Linux Framebuffer
全面的framebuffer详解 一.FrameBuffer的原理 FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口. Linux是工作在保护模式下,所以用户态进程是无法象D ...