NHibernate之旅(21):探索对象状态
本节内容
- 引入
- 对象状态
- 对象状态转换
- 结语
引入
在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象。这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根据对象和当前会话的关联状态,我们可以把对象分为三种:
瞬时对象:对象刚刚建立。该对象在数据库中没有记录,也不在ISession缓存中。如果该对象是自动生成主键,则该对象的对象标识符为空。
持久化对象:对象已经通过NHibernate进行了持久化,数据库中已经存在对应的记录。如果该对象是自动生成主键,则该对象的对象标识符已被赋值。
托管对象:该对象是经过NHibernate保存过或者从数据库中取出的,但是与之关联的ISession已经关闭。虽然它有对象标识符且数据库中存在对应记录,但是已经不再被NHibernate管理。
对象状态
NHibernate提供了对象状态管理的功能,支持三种对象状态:瞬时态(Transient)、持久态(Persistent)、托管态(Detached)。
1.瞬时态(Transient)
对象刚刚创建,还没有来及和ISession关联的状态。这时瞬时对象不会被持久化到数据库中,也不会被赋上标识符。如果不使用则被GC销毁。ISession接口可以将其转换为持久状态。
这像这样,刚刚创建了一个Customer对象,是一个瞬时态对象:
var customer = new Customer() { Firstname = "YJing", Lastname = "Lee" };
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 = "YJidng", Lastname = "Lee" };
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 += "YJingLee";
Assert.IsTrue(_session.Contains(customer));
//重新设置ISession
ResetSession();
Assert.IsFalse(_session.Contains(customer));
//托管态对象
//在托管态下可继续被修改
customer.Firstname += "CnBlogs";
//这时一起更新
_transaction.UpdateCustomerTransaction(customer);
//转变为持久态对象
Assert.IsTrue(_session.Contains(customer));
}
这个加上一个锁:如果在托管时期没有修改,就不执行更新语句,只转换为持久态,下面的例子如果在托管时期修改对象,执行更新语句。
[Test]
public void DetachedConvertPersistentUpdateLockTest()
{
Customer customer = _transaction.GetCustomerById(1);
Assert.IsTrue(_session.Contains(customer));
ResetSession();
Assert.IsFalse(_session.Contains(customer));
//锁
_session.Lock(customer, NHibernate.LockMode.None);
//如果在托管时期没有修改,就不执行更新语句,只转换为持久态
//customer.Firstname += "CnBlogs";
_transaction.UpdateCustomerTransaction(customer);
Assert.IsTrue(_session.Contains(customer));
}
方法二:ISession.Merge():合并指定实例。不必考虑ISession状态,ISession中存在相同标识的持久化对象时,NHibernate便会根据用户给出的对象状态覆盖原有的持久化实例状态。
方法三:ISession.SaveOrUpdate():分配新标识保存瞬时态对象;更新/重新关联托管态对象。
以上两个大家自己测试了!
结语
这篇初步知道了对象的状态。虽然对象的状态的细节由NHibernate自己维护,但是对象状态在NHibernate应用中还是比较重要的。同时对象状态也涉及了NHibernate缓存、离线查询等内容。
NHibernate之旅(21):探索对象状态的更多相关文章
- [Nhibernate]对象状态
目录 写在前面 文档与系列文章 对象状态 瞬时态(Transient) 持久态(Persistent) 托管态(Detached) 对象状态转换 总结 写在前面 前面两篇文章介绍了SchemaExpo ...
- NHibernate教程(18)--对象状态
本节内容 引入 对象状态 对象状态转换 结语 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的 ...
- NHibernate之旅系列文章导航
NHibernate之旅系列文章导航 宣传语 NHibernate.NHibernate教程.NHibernate入门.NHibernate下载.NHibernate教程中文版.NHibernate实 ...
- NHibernate系列文章七:NHibernate对象状态
摘要 NHibernate对象持久化 NHibernate对象的三个状态:临时态.持久态.游离态(托管态) NHibernate三状态的相互转化 1. NHibernate对象持久化 NHiberna ...
- [转]NHibernate之旅(11):探索多对多关系及其关联查询
本节内容 多对多关系引入 多对多映射关系 多对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 多对多关系引入 让我们再次回顾在第二篇中建立的数据模型 ...
- NHibernate之旅(18):初探代码生成工具使用
本节内容 引入 代码生成工具 结语 引入 我们花了大量的篇幅介绍了相关NHibernate的知识.一直都是带着大家手动编写代码,首先创建数据库架构.然后编写持久化类和映射文件,最后编写数据操作方法.測 ...
- hibernate学习(5)——对象状态与一级缓存
1.对象状态 1.1 状态介绍 hibernate 规定三种状态:瞬时态.持久态.脱管态 瞬时态:transient,session没有缓存对象,数据库也没有对应记录.没有与hibernate关联 ...
- Entity Framework 实体框架的形成之旅--利用Unity对象依赖注入优化实体框架(2)
在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...
- ArcGIS Engine开发之旅09--几何对象和空间参考
原文:ArcGIS Engine开发之旅09--几何对象和空间参考 1.Geometry Geometry 是 GIS 中使用最为广泛的对象集之一,用户在创建.删除.编辑和进行地理分析的时候,就是处 ...
随机推荐
- ConcurrentHashMap 的实现原理
概述 我们在之前的博文中了解到关于 HashMap 和 Hashtable 这两种集合.其中 HashMap 是非线程安全的,当我们只有一个线程在使用 HashMap 的时候,自然不会有问题,但如果涉 ...
- JavaScript变量作用域(Variable Scope)和闭包(closure)的基础知识
在这篇文章中,我会试图讲解JavaScript变量的作用域和声明提升,以及许多隐隐藏的陷阱.为了确保我们不会碰到不可预见的问题,我们必须真正理解这些概念. 基本定义 作用范围是个“木桶”,里面装着变量 ...
- [Canvas]Bombman v1.00
爆破小人Canvas版,请点此下载,并用浏览器打开试玩. 图例: 源码: <!DOCTYPE html> <html lang="utf-8"> <m ...
- SublimeText SFTP连接Amazon EC2
文章最初发表于szhshp的第三边境研究所 转载请注明 1. SublimeText SFTP连接Amazon EC2 Sublime Text 3 正式版发布了,全平台IDE果断都换了. 今天终于有 ...
- 访问 Google
对于一个技术人员访问Google是何其的重要呀? 一下收集了一些访问的连接,不愿意使用VPS的同学可以使用下: 非原版: Glgoo:http://www.glgoo.com/九尾搜索:http:// ...
- oracle decode()函数的参数原来可以为sql语句!
1.情景展示 判断某个字段的值,如果以APP开头,需查询APP表里对应的数据:如果是以JG开头,就查询机构对应的表. 2.原因分析 如果使用CASE WHEN THEN或者IF ELSIF 太麻烦 ...
- GitHub下载安装以及开源项目
Git for Windows安装与使用 http://cioworld.org/freedom/content/git-windows 下载Git-1.8.3-preview20130601.exe ...
- linux下查看端口占用
1. lsof -i:端口号 用于查看某一端口的占用情况 需要注意的是,centos默认是没有安装lsof(list open files)的,需要手动安装 yum install lsof 各列代表 ...
- iOS 测试版系统安装说明(粗略翻译)
我们常常看到在https://developer.apple.com/download/这里会有beta版本的ios系统 或者开发软件 关于beta版本的应用,其实有很大用处,好多人会在正式版没有发布 ...
- JS放在博客里面运行
<ol><li>测试的内容</li><li>测试的内容</li><li>测试的内容</li><li>测试 ...