• 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之查询缓存


    打开查询缓存,

    第一步:需要在hbernate.cfg.xml中设置:

        <!--4.启动查询缓存-->
        <property name="cache.use_query_cache">true</property>

     第二步:需要显式的使用IQuery.SetCacheable(true)方法

            /// <summary>
            /// 使用查询缓存的HQL查询
            /// </summary>
            /// <param name="customerId"></param>
            /// <returns></returns>
            public Customer GetCustomerUsingHqlAndSetCacheable(int customerId)
            {
                Customer result = null;
                ISession session = _sessionManager.GetSession();
    
                try
                {
    
                    result = session.CreateQuery("from Customer c where c.CustomerId=:paraCustomerId")
                        .SetInt32("paraCustomerId", customerId)
                        .SetCacheable(true) //如果需要对查询缓存,还需要显式的使用IQuery.SetCacheable(true)方法
                        .List<Customer>().First();
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    session.Close();
                }
    
                return result;
            }

     测试一和结果:

            [TestMethod]
            public void TestSecondLevelCacheGetCustomerUsingHqlCustomerHavingNotOrders()
            {
                CustomerService customerService = new CustomerService();
    
                Customer customer = new Customer()
                {
                    FirstName = "Test",
                    LastName = "TestSessionFactoryCache",
                    Age = 10
                };
    
                customerService.Add(customer);
                int customerId = customer.CustomerId;
    
    
                Console.WriteLine("第1次获取数据------------------------------:");
                Customer customerGet1 = customerService.GetCustomerUsingHqlAndSetCacheable(customerId);
    
                Console.WriteLine("更新前:Id:{0}-->FirtstName:{1}"
                    , customerGet1.CustomerId, customerGet1.FirstName);
    
                Console.WriteLine("第2次获取数据==============================:");
                Customer customerGet2 = customerService.Get(customerId);
                Console.WriteLine("Id:{0}-->FirtstName:{1}"
                    , customerGet2.CustomerId, customerGet2.FirstName);
    
            }
    View Code
    NHibernate: 
        INSERT 
        INTO
            Customer
            (Version, Firstname, Lastname, Age) 
        VALUES
            (@p0, @p1, @p2, @p3);
        select
            SCOPE_IDENTITY();
        @p0 = 1 [Type: Int32 (0)],
        @p1 = 'Test' [Type: String (4000)],
        @p2 = 'TestSessionFactoryCache' [Type: String (4000)],
        @p3 = 10 [Type: Int32 (0)]
    第1次获取数据------------------------------:
    NHibernate: 
        select
            customer0_.CustomerId as CustomerId0_,
            customer0_.Version as Version0_,
            customer0_.Firstname as Firstname0_,
            customer0_.Lastname as Lastname0_,
            customer0_.Age as Age0_ 
        from
            Customer customer0_ 
        where
            customer0_.CustomerId=@p0;
        @p0 = 216 [Type: Int32 (0)]
    更新前:Id:216-->FirtstName:Test
    第2次获取数据==============================:
    Id:216-->FirtstName:Test
    View Code

    测试二和结果:

            [TestMethod]
            public void TestSecondLevelCacheGetCustomerUsingHqlCustomerHavingOrders()
            {
                CustomerService customerService = new CustomerService();
    
                Customer customer = new Customer()
                {
                    FirstName = "Test",
                    LastName = "TestSessionFactoryCache",
                    Age = 10
                };
    
                Order order1 = new Order()
                {
                    OrderDate = DateTime.Now,
                    Customer = customer
                };
                customer.Orders.Add(order1);
    
                customerService.Add(customer);
                int customerId = customer.CustomerId;
    
    
                Console.WriteLine("第1次获取数据------------------------------:");
                Customer customerGet1 = customerService.GetCustomerUsingHqlAndSetCacheable(customerId);
    
                Console.WriteLine("更新前:Id:{0}-->FirtstName:{1}"
                    , customerGet1.CustomerId, customerGet1.FirstName);
    
                Console.WriteLine("第2次获取数据==============================:");
                Customer customerGet2 = customerService.GetCustomerUsingHqlAndSetCacheable(customerId);
                Console.WriteLine("Id:{0}-->FirtstName:{1}"
                    , customerGet2.CustomerId, customerGet2.FirstName);
    
            }
    View Code
    NHibernate: 
        INSERT 
        INTO
            Customer
            (Version, Firstname, Lastname, Age) 
        VALUES
            (@p0, @p1, @p2, @p3);
        select
            SCOPE_IDENTITY();
        @p0 = 1 [Type: Int32 (0)],
        @p1 = 'Test' [Type: String (4000)],
        @p2 = 'TestSessionFactoryCache' [Type: String (4000)],
        @p3 = 10 [Type: Int32 (0)]
    NHibernate: 
        INSERT 
        INTO
            [
            
        Order] (
            Version, OrderDate, CustomerId
        ) 
    VALUES
        (@p0, @p1, @p2);
        select
            SCOPE_IDENTITY();
        @p0 = 1 [Type: Int32 (0)],
        @p1 = 2014/5/30 0:52:54 [Type: DateTime (0)],
        @p2 = 217 [Type: Int32 (0)]
    第1次获取数据------------------------------:
    NHibernate: 
        select
            customer0_.CustomerId as CustomerId0_,
            customer0_.Version as Version0_,
            customer0_.Firstname as Firstname0_,
            customer0_.Lastname as Lastname0_,
            customer0_.Age as Age0_ 
        from
            Customer customer0_ 
        where
            customer0_.CustomerId=@p0;
        @p0 = 217 [Type: Int32 (0)]
    更新前:Id:217-->FirtstName:Test
    第2次获取数据==============================:
    Id:217-->FirtstName:Test
    View Code

     ---------------------------------------------------------------

    其他资料:

    启用缓存查询

    在NHibernate中,除了缓存持久化类和集合外,查询结果集也可以缓存。如果程序中经常使用同样的条件查询数据,则可以使用查询缓存。在配置文件中可以指定启动查询缓存

    <property name="cache.use_query_cache">true</property>

    查询缓存后,NHibernate将创建两个缓存区域。一个用于保存查询结果集,由NHibernate.Cache.StandardQueryCache实现。一个用来保存最近更新的查询表的时间截,由NHibernate.Cache.UpdateTimestampsCache实现。

    查询缓存中的结果集并不是永久有效的。当缓存的查询语句对应的数据库发生改变时,该缓存结果随之失效。因而对大多数查询而言,查询缓存的益处不是很大,所以NHibernate在默认情况下不对查询进行缓存。

    如果需要对查询缓存,还需要显式的使用IQuery.SetCacheable(true)方法。IQuery调用这个方法后,NHibernate将根据查询语句、查询参数、结果集起始范围等信息组成一个IQueryKey。接着根据这个IQueryKey到查询缓存中查找相应数据,查询成功则直接返回查找结果。否则,查询数据库,获取结果集,并把结果集根据IQueryKey放入查询缓存。如果IQueryKey数据发生改变(增加、删除、修改等),这些IQueryKey及其对象的结果集将从缓存中删除。

    测试2:显式启用缓存查询

    这个例子显式使用IQuery.SetCacheable(true)方法缓存查询结果,第二次查询相同条件时,直接从缓存查询中读取。

    [Test]

    public void QueryCacheTest()

    {

        using (_session)

        {

            Console.WriteLine("第一次查询某数据,显式缓存查询结果");

            IList<Customer> customers =

                _session.CreateQuery("from Customer c where c.CustomerId > 2")

                .SetCacheable(true)

                .List<Customer>();

            Assert.AreEqual(11, customers.Count);

        }

        ResetSession();

        using (_session)

        {

            Console.WriteLine("第二次查询某数据,显式缓存查询结果");

            IList<Customer> customers =

                _session.CreateQuery("from Customer c where c.CustomerId > 2")

                .SetCacheable(true)

                .List<Customer>();

            Assert.AreEqual(11, customers.Count);

        }

    }

    测试3:指定命名缓存区域

    我们还可以使用.SetCacheRegion("cacheRegion"), 给查询缓存指定了特定的命名缓存区域,该查询缓存的缓存策略将由二级缓存的命名区域负责:

    [Test]

    public void QueryCacheTest()

    {

        using (_session)

        {

            Console.WriteLine("第一次查询某数据,显式缓存查询结果");

            IList<Customer> customers =

                _session.CreateQuery("from Customer c where c.CustomerId > 2")

                .SetCacheable(true)

                .SetCacheRegion("queryCache")

                .List<Customer>();

            Assert.AreEqual(11, customers.Count);

        }

        ResetSession();

        using (_session)

        {

            Console.WriteLine("第二次查询某数据,显式缓存查询结果");

            IList<Customer> customers =

                _session.CreateQuery("from Customer c where c.CustomerId > 2")

                .SetCacheable(true)

                .SetCacheRegion("queryCache")

                .List<Customer>();

            Assert.AreEqual(11, customers.Count);

        }

    }

    测试结果说明:第一次查询出来的结果集被存储在名为queryCache的缓存区域,第二次同样在这个缓存区域里寻找需要数据,如果第二次没有指定或者指定别的缓存区域则没有需要的数据,就要到数据库中查询了。

     

    测试4:命名查询

    可以在映射文件中定义命名查询,<query>元素提供了很多属性,可以用于缓存结果,这里,我举一个例子吧,在Customer.hbm.xml映射文件中定义名为selectCustomer的查询由于查询所有Customer并启用缓存查询,缓存模式为默认方式(下面有说明)

    <query cacheable ="true" cache-mode="normal" name="selectCustomer">

      from Customer

    </query>

    编写一个方法:

    [Test]

    public void NamedQueryCacheTest()

    {

        using (_session)

        {

            Console.WriteLine("--->第一次使用命名查询");

            IList<Customer> customers = _session.GetNamedQuery("selectCustomer")

                .List<Customer>();

        }

        ResetSession();

        using (_session)

        {

            Console.WriteLine("--->第二次使用命名查询");

            IList<Customer> customers = _session.GetNamedQuery("selectCustomer")

                .List<Customer>();

        }

    }

    NHibernate提供的查询(HQL、条件查询、原生SQL查询)都类似,我在这里就不重复举例了,大家可以测试下。

    管理NHibernate二级缓存

       NHibernate二级缓存由ISessionFactory创建并由ISessionFactory自行维护。我们使用NHibernate操作数据时,ISessionFactory能够自动同步缓存,保证缓存的有效性。但是当我们批量操作数据时,往往NHibernate不能维护缓存持久有效。ISessionFactory提供了可编程方式的缓存管理方法。

    ISessionFactory提供了一系列的EvictXXX()方法可以方便的从二级缓存中删除一个实例、删除一个集合、一个命名缓存等操作

    •Evict(persistentClass):从二级缓存中删除persistentClass类所有实例

    •Evict(persistentClass, id):从二级缓存中删除指定的持久化实例

    •EvictEntity(entityName):从二级缓存中删除命名实例

    •EvictCollection(roleName):从二级缓存中删除集合

    •EvictCollection(roleName, id):从二级缓存中删除指定的集合

    •EvictQueries():从二级缓存中刷新全部查询结果集

    •EvictQueries(cacheRegion):从二级缓存中刷新指定查询结果集

    ISession内置缓存可以共享ISessionFactory缓存,通过指定ISession的CacheMode可以控制ISession和ISessionFactory的交互方式。ISession可以通过以下五种方式和ISessionFactory交互:

    •Ignore:更新数据时将二级缓存失效,其它时间不和二级缓存交互

    •Put:向二级缓存写数据,但不从二级缓存读数据

    •Get:从二级缓存读数据,仅在数据更新时向二级缓存写数据

    •Normal:默认方式。从二级缓存读/写数据

    •Refresh:向二级缓存写数据,想不从二级缓存读数据,通过在配置文件设置cache.use_minimal_puts从数据库中读取数据时,强制二级缓存刷新

     

  • 相关阅读:
    装饰器
    目录和文件操作
    网络通信过程
    epoll并发
    laravel(包含lumen)框架中的跨域函数实例
    windows使用nginx
    nginx反向代理配置 其实很简单
    前端html页面使用marked点亮你的代码
    PHPWAMP开启SSL,PHPWAMP配置ssl证书
    php接收并存储base64位字符串图片
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/3760332.html
Copyright © 2020-2023  润新知