• 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缓存、离线查询等内容。

  • 相关阅读:
    关于bootstrap的css样式总结
    SpringCloudConfig分布式配置中心
    static 关键字的作用-------王志亭
    java 学习当中我遇到的第一个设计模式-----王志亭
    在java 多态 中 父类作为参数列表的方法
    强悍的蒙古人---王志亭
    蒙古人--巴特尔
    乌兰巴托----王志亭
    不一样的插入方法-------王志亭
    乌兰巴托的思念--------------王志亭
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/3758209.html
Copyright © 2020-2023  润新知