NHibernate之一级缓存(第十篇)
2015-12-09 09:56
288 查看
NHibernate之一级缓存(第十篇)
NHibernate的一级缓存,名词好像很牛B,很难。实际上就是ISession缓存。存储在ISession的运行周期内。而二级缓存则存储在ISessionFactory内。
示例:
首先我们先开启配置文件中的show_sql节点:
PersonDao.cs
Program.cs
输出:
![](http://images.cnitblog.com/blog/347600/201309/11210529-0948086d1f394d5ebee38d05c3618d19.jpg)
我们看到只有第一次查询执行了SQL语句,第二次并没有执行任何语句。这点从SQL Server Profiler中也可监控到。
![](http://images.cnitblog.com/blog/347600/201309/11210647-d4915e265c5548598624ea86f48b97a7.jpg)
在两个会话中获得同一实例
下面我们把
sessionFactory.OpenSession();
这行代码放到方法里面会怎么样呢?
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11210953-c4678e81baff44e7a23ed69a2dd899a4.jpg)
留意到每OpenSession一次,缓存就没有了。OpenSession一次,NHibernate会自动释放原有的ISession对象。
看到这里,你应该懂得注意下自己代码的写法了。
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11215815-e952a6702ff04f2f9b81dfdb1b069708.jpg)
留意到Get()执行的时候,就立即到数据库读取了。而Load()是延迟加载,到要用的时候,采取数据库读取,不用不读。
不用Get<>或Load<>能否缓存
下面我们把PersonDao改成这样:
Program.cs
输出:
![](http://images.cnitblog.com/blog/347600/201309/11220553-293a6e3f971048a6bf0c08f502684eac.jpg)
留意到,还是执行了两次SQL语句。看来,只有Get()或Load()才能使用NHibernate的一级缓存。
如我们回到本文的第一个示例,只改如下加粗的代码:
Program.cs
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11221122-1cd473945acd4d4fa9a0ca7464fdcfc9.jpg)
可以看到NHibernate还是老老实实执行了两次SQL语句。
NHibernate提供了如下三个方法,让我们管理一级缓存。
ISession.Evict(object):从缓存中删除指定实例。
ISession.Clear():清空缓存。
ISession.Contains(object):检查缓存中是否包含指定实例。
ISession.Refresh(object):刷新缓存中的单个实例。
一个示例说明问题:
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11222233-5e0b72de6b4540d9bbe715d0e0c231f9.jpg)
刷新缓存:
输出结果:
![](http://images.cnitblog.com/blog/347600/201309/11223010-eac07e5195f64f1dac1a55540da8e559.jpg)
可以看到3秒钟之后,NHibernate重新查询了一次数据库,获得最新的对象。
NHibernate的一级缓存,名词好像很牛B,很难。实际上就是ISession缓存。存储在ISession的运行周期内。而二级缓存则存储在ISessionFactory内。
一、ISession一级缓存测试
ISession默认开启一级缓存,不需要任何配置。ISession缓存在ISession创建后就可以使用,以后每次通过此 ISession操作数据时,ISession会检测自身是否缓存有相应的数据,如果有则直接返回。如果没有,这时才查询数据库返回,同时缓存到 ISession。当释放ISession实例的时候,缓存自动销毁。示例:
首先我们先开启配置文件中的show_sql节点:
<property name="show_sql">true</property> //开启这个对本缓存测试没影响,只是看看效果
PersonDao.cs
public class PersonDao { ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory(); ISession session; public PersonDao() { session = sessionFactory.OpenSession(); } public PersonModel GetPersonById(int Id) { PersonModel p = session.Get<PersonModel>(Id); return p; } }
Program.cs
class Program { static void Main(string[] args) { PersonDao dao = new PersonDao(); //第一次读取 PersonModel p1 = dao.GetPersonById(3); Console.WriteLine(p1.Id + " " + p1.Name); //第二次读取 PersonModel p2 = dao.GetPersonById(3); Console.WriteLine(p2.Id + " " + p2.Name); Console.ReadKey(); } }
输出:
![](http://images.cnitblog.com/blog/347600/201309/11210529-0948086d1f394d5ebee38d05c3618d19.jpg)
我们看到只有第一次查询执行了SQL语句,第二次并没有执行任何语句。这点从SQL Server Profiler中也可监控到。
![](http://images.cnitblog.com/blog/347600/201309/11210647-d4915e265c5548598624ea86f48b97a7.jpg)
在两个会话中获得同一实例
下面我们把
sessionFactory.OpenSession();
这行代码放到方法里面会怎么样呢?
public PersonModel GetPersonById(int Id) { ISession session = sessionFactory.OpenSession(); PersonModel p = session.Get<PersonModel>(Id); return p; }
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11210953-c4678e81baff44e7a23ed69a2dd899a4.jpg)
留意到每OpenSession一次,缓存就没有了。OpenSession一次,NHibernate会自动释放原有的ISession对象。
看到这里,你应该懂得注意下自己代码的写法了。
二、ISession.Get()与ISession.Load()的区别
不想废话,十几行代码说明问题:static void Main(string[] args) { ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory(); ISession session = sessionFactory.OpenSession(); Console.WriteLine("Get之前"); PersonModel pGet = session.Get<PersonModel>(1); Console.WriteLine("Get之后"); Console.WriteLine("读取名字" + pGet.Name); Console.WriteLine("====================================="); Console.WriteLine("Load之前"); PersonModel pLoad = session.Load<PersonModel>(2); Console.WriteLine("Load之后"); Console.WriteLine("读取名字" + pLoad.Name); Console.ReadKey(); }
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11215815-e952a6702ff04f2f9b81dfdb1b069708.jpg)
留意到Get()执行的时候,就立即到数据库读取了。而Load()是延迟加载,到要用的时候,采取数据库读取,不用不读。
不用Get<>或Load<>能否缓存
下面我们把PersonDao改成这样:
public class PersonDao { ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory(); ISession session; public PersonDao() { session = sessionFactory.OpenSession(); } public IList<PersonModel> GetPersonList() { return session.QueryOver<PersonModel>().List(); } }
Program.cs
static void Main(string[] args) { PersonDao dao = new PersonDao(); IList<PersonModel> PersonList1 = dao.GetPersonList(); Console.WriteLine(PersonList1[0].Name); IList<PersonModel> PersonList2 = dao.GetPersonList(); Console.WriteLine(PersonList1[0].Name); Console.ReadKey(); }
输出:
![](http://images.cnitblog.com/blog/347600/201309/11220553-293a6e3f971048a6bf0c08f502684eac.jpg)
留意到,还是执行了两次SQL语句。看来,只有Get()或Load()才能使用NHibernate的一级缓存。
三、一级缓存的管理
当我们使用Get()或Load()的时候,不想使用一级缓存怎么办呢?答案,使用如我们回到本文的第一个示例,只改如下加粗的代码:
public class PersonDao { ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory(); IStatelessSession session; public PersonDao() { session = sessionFactory.OpenStatelessSession(); } public PersonModel GetPersonById(int Id) { PersonModel p = session.Get<PersonModel>(Id); return p; } }
Program.cs
static void Main(string[] args) { PersonDao dao = new PersonDao(); //第一次读取 PersonModel p1 = dao.GetPersonById(3); Console.WriteLine(p1.Id + " " + p1.Name); //第二次读取 PersonModel p2 = dao.GetPersonById(3); Console.WriteLine(p2.Id + " " + p2.Name); Console.ReadKey(); }
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11221122-1cd473945acd4d4fa9a0ca7464fdcfc9.jpg)
可以看到NHibernate还是老老实实执行了两次SQL语句。
NHibernate提供了如下三个方法,让我们管理一级缓存。
ISession.Evict(object):从缓存中删除指定实例。
ISession.Clear():清空缓存。
ISession.Contains(object):检查缓存中是否包含指定实例。
ISession.Refresh(object):刷新缓存中的单个实例。
一个示例说明问题:
static void Main(string[] args) { ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory(); ISession session = sessionFactory.OpenSession(); PersonModel p1 = session.Get<PersonModel>(1); PersonModel p2 = session.Get<PersonModel>(2); PersonModel p3 = new PersonModel(); Console.WriteLine(session.Contains(p1)); //输出True Console.WriteLine(session.Contains(p2)); //输出True session.Evict(p1); //从一级缓存中移除p1,看你还Con不Contains Console.WriteLine(session.Contains(p1)); //输出False Console.WriteLine(session.Contains(p2)); //输出True session.Clear(); //全部清空,看你还Con不Containsp2 Console.WriteLine(session.Contains(p2)); //输出False Console.ReadKey(); }
输出结果如下:
![](http://images.cnitblog.com/blog/347600/201309/11222233-5e0b72de6b4540d9bbe715d0e0c231f9.jpg)
刷新缓存:
static void Main(string[] args) { ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory(); ISession session = sessionFactory.OpenSession(); PersonModel p1 = session.Get<PersonModel>(1); Thread.Sleep(3000); Console.WriteLine("3秒钟之后----------------"); session.Refresh(p1); Console.ReadKey(); }
输出结果:
![](http://images.cnitblog.com/blog/347600/201309/11223010-eac07e5195f64f1dac1a55540da8e559.jpg)
可以看到3秒钟之后,NHibernate重新查询了一次数据库,获得最新的对象。
相关文章推荐
- 夺命雷公狗---javascript NO:16 默认行为1
- ImageView的src和background的区别
- UVa 11548 例题9-7划分回文串
- Spring MVC+Hibernate框架项目开发流程
- 解决“org.apache.hadoop.security.AccessControlException”
- DecimalFormat(数字格式化) SimpleDateFormat(时间格式化)
- 抽奖概率
- 销售管理系统一般价格是多少钱?
- YII framewoke
- 山东大学软件工程复习纲要
- 态度
- NHibernate 之数据操作 (第五篇)
- NHibernate Linq查询 扩展增强 (第九篇)
- springmvc jsp中的css,js路径正确,但浏览器无法找到
- 接口与抽象类
- 几种经典的hash算法
- spark streaming+flume avro实时计算
- 华为内部的Web安全原则
- Linux软件安装(rpm和yum)
- python 装饰器