[Nhibernate]对象状态
目录
写在前面
前面两篇文章介绍了SchemaExport工具的使用,使用该工具可以根据映射文件生成数据库架构,这篇文章将介绍nhibernate中的三种对象状态。
在程序运行过程中,使用对象的方式操作数据库的同时,必然会产生一系列的持久化对象。这些对象可能是刚刚创建并准备进行存储的,也有可能是从数据库进行查询得到的,为了区别这些对象,根据对象和当前Session的关联状态,可以将对象分为三种:
瞬时对象:对象刚刚建立,该对象没有在数据库中进行存储,也没有在ISession的缓存中。如果该对象的主键是自动创建的,则此时对象的标识符为空。
持久化对象:对象已经通过Nhibernate进行了持久化,数据库中已经存在了该对象的记录。如果该对象自动创建主键,则此时对象的标识符已被赋值。
托管对象:该对象已经通过NHIbernate保存或者从数据库中查询取出的,但与此对象关联的ISession已经关闭。虽然它存在对象标识符,且在数据库中也有对应的记录,但已经不被Nhibernate管理的。
文档与系列文章
[NHibernate]持久化类(Persistent Classes)
[NHibernate]集合类(Collections)映射
[NHibernate]缓存(NHibernate.Caches)
[NHibernate]NHibernate.Tool.hbm2net
[NHibernate]Nhibernate如何映射sqlserver中image字段
[NHibernate]条件查询Criteria Query
[Nhibernate]SchemaExport工具的使用(一)——通过映射文件修改数据表
[Nhibernate]SchemaExport工具的使用(二)——创建表及其约束、存储过程、视图
对象状态
NHibernate提供了对象状态管理的功能,支持三种对象状态:瞬时态(Transient)、持久态(Persistent)、脱管态(Detached)。
瞬时态(Transient)
对象刚刚创建,还没有来及和ISession关联的状态。这时瞬时对象不会被持久化到数据库中,也不会被赋上标识符。如果不使用则被GC销毁。ISession接口可以将其转换为持久状态。
例如:刚刚创建一个Customer对象,就是一个瞬时态的对象。
//瞬时态对象
var customer = new Customer()
{
CustomerID = Guid.NewGuid(),
NameAddress = new Name()
{
CustomerAddress="北京",
CustomerName="wolfy"
},
Orders=null,
Version=
};
持久态(Persistent)
刚被保存的或刚从数据库中加载的。对象仅在关联的ISession生命周期内有效,在数据库中有相应记录并有标识符。对象实例由NHibernate框架管理,如果有任何改动,在提交时,与数据库同步,即将对象保存更新到数据库中。
脱管态(Detached)
持久对象关联的ISession关闭后,这个对象在ISession中脱离了关系,就是脱管态了,托管对象仍然有持久对象的所有属性,对托管对象的引用仍然有效的,我们可以继续修改它。如果把这个对象重新关联到ISession上,则再次转变为持久态,在托管时期的修改会被持久化到数据库中。
对象状态转换
在同步数据库的情况下执行下面的语句可以转换对象的状态。
ISession.Contains(object):检查ISession中是否包含指定实例
添加一个ISession的重置方法
1 public static ISession ResetSession()
2 {
3 if (_session.IsOpen)
4 _session.Close();
5 _session = _sessionFactory.OpenSession(); ;
6 return _session;
7 }
瞬时态转换为持久态
方法一:ISession.Save():保存指定实例。
public void TransientConvertPersistent()
{
//瞬时态对象
var customer = new Customer()
{
CustomerID = Guid.NewGuid(),
NameAddress = new Name()
{
CustomerAddress="北京",
CustomerName="wolfy"
},
Orders=null,
Version=
};
ISession session = NHibernateHelper.GetSession();
if (!session.Contains(customer))
{
//关联ISession保存到数据库中
session.Save(customer);
}
//变为持久态,由于表中CustomerId字段自动增长的(如果是自动增长主键),保存数据库,CustomerId字段自动加一
//经过NHibernate类型转换后返回CustomerId属性值,保证数据库与实例对象同步
if (session.Contains(customer))
{ }
}
方法二:ISession.SaveOrUpdate():分配新标识保存瞬时态对象。
持久态转换为脱管态
方法一:ISession.Evict(object):从当前ISession中删除指定实例
public void PersistentConvertDetachedEvict()
{
//得到session
ISession session = NHibernateHelper.GetSession();
//根据id得到customer对象
var customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));
//如果包含customer对象则删除
if (session.Contains(customer))
{
session.Evict(customer);
}
}
方法二:ISession.Close():关闭当前ISession
public void PersistentConvertDetachedCloseTest()
{
//得到session
ISession session = NHibernateHelper.GetSession();
//根据id得到customer对象
var customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));
if (session.Contains(customer))
{
NHibernateHelper.ResetSession();
}
}
脱管态转换为持久态
方法一:ISession.Update():更新指定实例。
public void DetachedConvertPersistentUpdateTest()
{
//得到session
ISession session = NHibernateHelper.GetSession();
//根据id得到customer对象
Customer customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8")) as Customer;
//重新设置ISession
NHibernateHelper.ResetSession();
//脱管态对象
//在脱管态下可继续被修改
if (session.Contains(customer))
{
customer.NameAddress = new Name() { CustomerAddress="上海", CustomerName="wolfy"};
//转变为持久态对象
session.Update(customer);
}
}
通过上面的例子可以看出:在托管时期的修改会被持久化到数据库中;
注意:NHibernate如何知道重新关联的对象是不是“脏的(修改过的)”?如果是新的ISession,ISession就不能与对象初值来比较这个对象是不是“脏的”,我们在映射文件中定义<id>元素和<version>元素的unsaved-value属性,NHibernate就可以自己判断了。
如果加上一个锁:如果在托管时期没有修改,就不执行更新语句,只转换为持久态,下面的例子如果在托管时期修改对象,执行更新语句。
public void DetachedConvertPersistentUpdateLockTest()
{
//得到session
ISession session = NHibernateHelper.GetSession();
//根据id得到customer对象
Customer customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8")) as Customer;
if (session.Contains(customer))
{
NHibernateHelper.ResetSession();
}
//锁
session.Lock(customer, NHibernate.LockMode.None);
//如果在托管时期没有修改,就不执行更新语句,只转换为持久态
session.Update(customer);
}
需注意Lock锁的使用,需要保证customer对象不为null,这里为了测试方便就没加上判断。如果为null会有异常(attempt to lock null)。
方法二:ISession.Merge():合并指定实例。不必考虑ISession状态,ISession中存在相同标识的持久化对象时,NHibernate便会根据用户给出的对象状态覆盖原有的持久化实例状态。
方法三:ISession.SaveOrUpdate():分配新标识保存瞬时态对象;更新/重新关联脱管态对象。
总结
本篇概念性的东西比较多,对三种状态的理解到位,就能区别三种状态。
参考文章
http://www.cnblogs.com/lyj/archive/2008/11/17/1335181.html
[Nhibernate]对象状态的更多相关文章
- NHibernate系列文章七:NHibernate对象状态
摘要 NHibernate对象持久化 NHibernate对象的三个状态:临时态.持久态.游离态(托管态) NHibernate三状态的相互转化 1. NHibernate对象持久化 NHiberna ...
- NHibernate教程(18)--对象状态
本节内容 引入 对象状态 对象状态转换 结语 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的 ...
- NHibernate之旅(21):探索对象状态
本节内容 引入 对象状态 对象状态转换 结语 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的 ...
- NHibernate系列文章八:NHibernate对象一级缓存
摘要 Nhibernatea缓存非常强大,按照缓存存储在Session对象还是SessionFactory对象分为一级缓存和二级缓存. 一级缓存存在于Session对象里,也叫Session缓存,由S ...
- hibernate学习(5)——对象状态与一级缓存
1.对象状态 1.1 状态介绍 hibernate 规定三种状态:瞬时态.持久态.脱管态 瞬时态:transient,session没有缓存对象,数据库也没有对应记录.没有与hibernate关联 ...
- [转]session缓存机制和三种对象状态
摘自 http://blog.csdn.net/csh624366188/article/details/7612142 Hibernate 的Session就是其中的一个,它提供了基本的增,删,改, ...
- Hibernate(四)之对象状态及一级缓存
一.Hibernate中的对象状态 1.1.瞬时态(临时态) 没有与Hibernate产生关联 与数据库中的记录没有产生关联(有关联就是与数据库中表的id相对应) 获得:一般都只直接创建(new) 瞬 ...
- 1.1Hibernate持久化类和Hibernate持久化对象状态
一.持久化对象po类 1.po定义 PO,是Persistent Object的缩写,是持久化类.PO是由PO=POJO+hbm映射配置组成. 2.通俗理解 PO类即持久化类,其实就是一个普通的Jav ...
- 【JAVAEE学习笔记】hibernate02:实体规则、对象状态、缓存、事务、批量查询和实现客户列表显示
一.hibernate中的实体规则 实体类创建的注意事项 1.持久化类提供无参数构造 2.成员变量私有,提供共有get/set方法访问.需提供属性 3.持久化类中的属性,应尽量使用包装类型 4.持久化 ...
随机推荐
- C++的友元类和友元函数实例
#include <math.h> #include<iostream> using namespace std; class Point { public: Point(do ...
- 浅谈Service层为何要有接口
被人随意问了一句,为何每个service层都要写一个接口呢,多麻烦~虽然想说点什么,但是又不知道从何说起,只好从新整理一下思绪. 情景1:在开源框架中有很多这种情况,就是某个功能支持用户自定义扩展.说 ...
- 匈牙利算法 cogs 886. [USACO 4.2] 完美的牛栏
886. [USACO 4.2] 完美的牛栏 ★★☆ 输入文件:stall4.in 输出文件:stall4.out 简单对比时间限制:1 s 内存限制:128 MB USACO/sta ...
- AC日记——校门外的树(增强版) 洛谷 P1276
题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是 ...
- WPF中监视DependencyProperty的变化
WPF中监视DependencyProperty的变化 周银辉 尽管一个类会提供很多事件,但有时候还是显得不够,比如说前两天我就以为WPF的ListBox控件会有ItemsSourceChange ...
- JSON.net 在实体类中自定义日期的格式
定义日期格式转换类,其继承 IsoDateTimeConverter,代码如下: public class DateTimeConverter : IsoDateTimeConverter { pub ...
- 去除phpcms会员登录后头部登陆条的会员名称的括号
phpcms会员登录后显示会员名称是带括号的,现在把他修改成不带括号. 找到函数库libs/functions/global.func.php,修改如下即可: function get_nicknam ...
- IoC 与 AOP (谈谈你对 Spring 的理解)
一.Spring 实现了工厂模式的工厂类,这个类名为BeanFactory(实际上是一个接口),在程序中通常 BeanFactory 的子类 ApplicationContext. Spring相当于 ...
- mariadb
MariaDB数据库管理系统是MySQL的一个分支
- C# 对 App.config的appSettings节点数据进行加密
.NET平台下的Winform和Asp.net的配置文件默认都是明文保存的,本文使用的是.Net自身如何加密配置文件,不包含自定义的加密规则 但.Net是提供了直接对配置文件加密的功能的,使用.Net ...