zoukankan      html  css  js  c++  java
  • NHibernate之旅(22):探索NHibernate一级缓存

    本节内容

    • 引入
    • NHibernate一级缓存介绍
    • NHibernate一级缓存管理
    • 结语

    引入

    大家看看上一篇了吗?对象状态。这很容易延伸到NHibernate的缓存。在项目中我们灵活的使用NHibernate的缓存机制。NHibernate性能会大大提高的哦,我们接下来就来探索NHibernate缓存机制吧,这篇我没有准备什么,先来学习下NHibernate一级缓存。

    NHibernate一级缓存介绍

    NHibernate一级缓存即ISession缓存,ISession缓存属于事务级缓存,是NHibernate内置的。ISession缓存中的数据只在本ISession周期内使用。

    ISession实例创建后即可使用ISession缓存。此后,ISession实例操作数据时,首先查询内置缓存,如果ISession缓存中存在相应数据,则直接使用缓存数据。如果不存在,则查询数据库并把其结果存在缓存中。

    实例1:查询一次持久化实例

    [Test]
    public void SessionCacheTest()
    {
        Customer customer = _transaction.GetCustomerById(1);
    }

    我们一般就是这样查询一条数据,NHibernate初始化ISession后,ISession缓存中不存在这个数据,这时NHibernate需要从数据库中加载数据。

    查询一次持久化实例

    实例2:一个会话装载两次持久化实例

    [Test]
    public void SessionCacheTest2()
    {
        Console.WriteLine("第一次读取持久化实例");
        Customer customer1 = _transaction.GetCustomerById(1);
        Console.WriteLine("第二次读取持久化实例");
        Customer customer2 = _transaction.GetCustomerById(1);
        Assert.AreSame(customer1, customer2);
    }

    第一次加载数据后,持久化实例放入缓存。第二次查询同一个持久化实例时,缓存中已经存在该持久化实例,应用程序将直接从缓存中获取数据,而不必再次从数据库中读取数据,这样同时也提高了查询效率,看看结果:

    一个会话装载两次持久化实例

    实例3:分别在两个会话中装载持久化实例

    [Test]
    public void SessionCacheTest3()
    {
        using (_session)
        {
            Console.WriteLine("--Session 1--读取持久化实例");
            Customer customer = _transaction.GetCustomerById(1);
            Assert.IsTrue(_session.Contains(customer));
        }
        ResetSession();
        using (_session)
        {
            Console.WriteLine("--Session 2--读取持久化实例");
            Customer customer = _transaction.GetCustomerById(1);
            Assert.IsTrue(_session.Contains(customer));
        }
    }

    在两个会话中获取同一持久化实例时,两个会话的缓存是独立的,一个会话的数据操作不会影响到另外一个会话。看看输出结果:

    分别在两个会话中装载持久化实例

    从结果我们可以说明虽然这两个会话读取的是同一个实例,但需要两次数据库操作,从而证明了Session缓存不是共享的,一个Session的缓存内容只有在本Session实例范围内可用。

    实例4:比较ISession.Get()和ISession.Load()

    不会吧,探索缓存比较这个?呵呵,如果你理解了它们的不同,或许你对NHibernate缓存还有一点了解了。开始。

    测试1:使用ISession.Get()方法按标识符获取Customer对象,访问标识符,再访问其它属性。

    [Test]
    public void GetExistingEntityTest()
    {
        Console.WriteLine("----获取持久化实例----");
        Customer customerGet = _session.Get<Customer>(1);
        Assert.IsNotNull(customerGet);
        Console.WriteLine("------访问这个实例的CustomerId属性------");
        Console.WriteLine("这个实例CustomerId属性:{0}", customerGet.CustomerId);
        Assert.AreEqual(customerGet.CustomerId, 1);
        Console.WriteLine("------访问这个实例的FirstName属性(不是CustomerId)-----");
        Console.WriteLine("这个实例的FirstName属性:{0}", customerGet.Name.Firstname);
    }

    直接看结果:

    获取对象

    测试2:使用ISession.Load()方法按标识符获取Customer对象,访问标识符,再访问其它属性。

    [Test]
    public void LoadExistingEntityTest()
    {
        Console.WriteLine("----加载持久化实例----");
        Customer customerLoad = _session.Load<Customer>(1);
        Assert.IsNotNull(customerLoad);
        Console.WriteLine("------访问这个实例的CustomerId属性----");
        Console.WriteLine("这个实例CustomerId属性:{0}", customerLoad.CustomerId);
        Assert.AreEqual(customerLoad.CustomerId, 1);
        Console.WriteLine("------访问这个实例的FirstName属性(不是CustomerId)----");
        Console.WriteLine("这个实例的FirstName属性:{0}", customerLoad.Name.Firstname);
    }

    看看结果:

    加载对象

    看到不同点了吗?这就是区别,我在测试中发现了这个秘密,使用ISession.Get()方法立即把对象实例保存到缓存中,使用ISession.Load()方法当你需要使用的时候再访问数据库把这个实例保存在缓存中。

    NHibernate一级缓存管理

    NHibernate为我们默认提供了一级缓存,那么我们想显式地去管理ISession缓存,怎么办呢?ISession接口为我们提供了一些方法来显式管理一级缓存。

    ISession.Evict(object):从缓存中删除指定实例。

    ISession.Clear():清空缓存。

    ISession.Contains(object):检查缓存中是否包含指定实例。

    实例分析

    我们写一个测试来看看如何显式管理吧:

    [Test]
    public void SessionCacheManageTest()
    {
        //1.加载两个实例放入ISession缓存
        Customer customer1 = _transaction.GetCustomerById(1);
        Customer customer2 = _transaction.GetCustomerById(2);
        //2.加载实例后,缓存包含两个实例
        Assert.IsTrue(_session.Contains(customer1));
        Assert.IsTrue(_session.Contains(customer2));
        //3.从缓存中删除Customer1实例
        _session.Evict(customer1);
        Assert.IsFalse(_session.Contains(customer1));
        Assert.IsTrue(_session.Contains(customer2));
        //4.清空ISession缓存,实例不和缓存关联
        _session.Clear();
        Assert.IsFalse(_session.Contains(customer1));
        Assert.IsFalse(_session.Contains(customer2));
    }

    首先,我们加载两个Customer对象,先使用ISession.Evict(object)从缓存中删除一个Customer对象,再使用ISession.Clear()清空缓存,使用Session.Contains(object)检查缓存中的Customer对象。

    结语

    关于NHibernate一级缓存的内容就这些了,相信你对NHibernate一级缓存有了初步的认识。接下来慢慢探索NHibernate二级缓存吧。

    本系列链接:NHibernate之旅系列文章导航

    NHibernate Q&A

    下次继续分享NHibernate!


    作者:李永京YJingLee's Blog
    出处:http://lyj.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    java.lang.NoSuchMethodError:antlr.collections.AST.getLine() I
    T7 java Web day01 标签HTML
    T6 s1 day19
    T5 s5 Day18
    T5 s4 Day 17
    T5 s3 day16
    T5 s2 Day 15
    T5 s1 day14
    T4 S03 day 12
    T4 S01 day1
  • 原文地址:https://www.cnblogs.com/lyj/p/1340253.html
Copyright © 2011-2022 走看看