本节内容

  • 引入
  • 对象状态
  • 对象状态转换
  • 结语

引入

在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象。这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根据对象和当前会话的关联状态,我们可以把对象分为三种:

瞬时对象:对象刚刚建立。该对象在数据库中没有记录,也不在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教程(18)--对象状态的更多相关文章

  1. [Nhibernate]对象状态

    目录 写在前面 文档与系列文章 对象状态 瞬时态(Transient) 持久态(Persistent) 托管态(Detached) 对象状态转换 总结 写在前面 前面两篇文章介绍了SchemaExpo ...

  2. NHibernate之旅(21):探索对象状态

    本节内容 引入 对象状态 对象状态转换 结语 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的 ...

  3. NHibernate系列文章七:NHibernate对象状态

    摘要 NHibernate对象持久化 NHibernate对象的三个状态:临时态.持久态.游离态(托管态) NHibernate三状态的相互转化 1. NHibernate对象持久化 NHiberna ...

  4. [译]Vulkan教程(18)命令buffers

    [译]Vulkan教程(18)命令buffers Command buffers 命令buffer Commands in Vulkan, like drawing operations and me ...

  5. HIbernate的对象状态

    *临时状态对象: session中没有缓存,且在数据库中没有对应数据. User user1=new User(null,"c50",18); *持久化状态对象: session中 ...

  6. NHibernate教程

    NHibernate教程 一.NHibernate简介 在今日的企业环境中,把面向对象的软件和关系数据库一起使用可能是相当麻烦.浪费时间的.NHibernate是一个面向.Net环境的对象/关系数据库 ...

  7. NHibernate教程(19) —— 一级缓存

    本节内容 引入 NHibernate一级缓存介绍 NHibernate一级缓存管理 结语 引入 大家看看上一篇了吗?对象状态.这很容易延伸到NHibernate的缓存.在项目中我们灵活的使用NHibe ...

  8. NHibernate教程(11)--多对多关联查询

    本节内容 多对多关系引入 多对多映射关系 多对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 多对多关系引入 让我们再次回顾在第二篇中建立的数据模型 ...

  9. nhibernate教程(4)--条件查询(Criteria Query)

    NHibernate之旅(4):探索查询之条件查询(Criteria Query) 2008-10-16 18:20 by 李永京, 44341 阅读, 43 评论, 收藏,  编辑 本节内容 NHi ...

随机推荐

  1. centos7安装docker并安装jdk和tomcat(常用命令)

    阿里专属的镜像加速 在宿主机器编辑文件:vi /etc/docker/daemon.json 阿里专属的镜像加速地址,类似于"https://91cntlkt.mirror.aliyuncs ...

  2. java 各种去空格的方法

    String str =" dgd fdgd ";   方法一:str = str.trim();//去前后空格 返回:dgd fdgd   方法二:str = str.repla ...

  3. C++标准库string

    C++标准库string 定义和初始化 string s1 默认初始化,s1是一个空串 string s2(s1) s2是s1的副本 string s2 = s1 等价于s2(s1),s2是s1的副本 ...

  4. jQuery实现拼图小游戏

    小熊维尼拼图                                                                                    2017-07-23 ...

  5. Python学习笔记2:构造序列:列表推导和生成器表达式

    欢迎访问个人网站:www.comingnext.cn 1. 关于Python内置序列类型 a. 按能否存放不同类型的数据区分 容器序列: list.tuple 和collections.deque这些 ...

  6. python编码错误

    初学python,遇到的最难忘的坑没有之一.这个问题起码困扰了我一周.在我写了一段代码之后经常遇见这样的报错. 本质原因是我用的python2,在编码流派中python2是比较奇葩的一派,不随大流.所 ...

  7. 2017多校第10场 HDU 6181 Two Paths 次短路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路. 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证 ...

  8. 【2016北京集训测试赛(十)】 Azelso (期望DP)

    Time Limit: 1000 ms   Memory Limit: 256 MB Description 题解 状态表示: 这题的状态表示有点难想...... 设$f_i$表示第$i$个事件经过之 ...

  9. 你所不知道的 CSS 动画技巧与细节

    怕标题起的有点大,下述技巧如果你已经掌握了看看就好,欢迎斧正,本文希望通过介绍一些 CSS 不太常用的技巧,辅以一些实践,让读者可以更加深入的理解掌握 CSS 动画. 废话少说,直接进入正题,本文提到 ...

  10. java web轻量级开发面试教程内容精粹:哪些简历得不到面试机会

    看到一本较好的实践性比较强的书,java web轻量级开发面试教程,里面的一些内容很有实践意义. 问题点 很难获得面试机会的原因 学历不符,比如要求是本科以上,但学历是大专 学历是硬指标,所以达不到学 ...