明思义 发表于 2025-5-30 08:11:33

NHibernate考察系列 06 进阶篇

    1. 实体生命周期
    Transient: 临时状态。代码中使用new创建一个实体的对象实例时,其状态为transient。
    Persistent: 持久化状态。实体的对象实例跟数据库中一条记录对应,并且其session处于活动状态。例如使用session.Get()方法加载的实体对象、使用session.Save()保存过的实体对象,在session关闭以前其状态为persistent。Transient状态的对象调用session.Save()、session.Update()等方法,并且session未关闭,其状态变成persistent。
    Detached: 游离状态。实体的对象实例跟数据库中一条记录对应,并且其session处于非活动状态。Persistent状态的对象,在对应的session关闭之后,其状态变成detaiched。Detached对象可以重新跟某个session建立联系,被这个session管理起来,例如对detached对象调用session.Update()。

    Persistent状态的对象是受管理的对象,它被放置在当前session的管理容器中,对其属性的修改会被记录,当session的事务提交时,所有这些更新修改会被提交到数据库。Transient和detached状态的对象不受管理。
    Transient和detached状态的区别是,对detached状态的对象,能够确定它跟数据库中的一条记录对应,而transient状态则不一定。NHibernate有很多的实体id生成方法,不少情况下transient状态的对象id属性没有值,只有在执行session.Save()过程中才会生成id值。Detached对象的各个属性都是完整的(跟数据库中的记录对应),包括id属性值。如果对象的id设置成由程序代码指定的方式,则你在代码中new一个对象,通过给该对象各个属性设置值,也可以使它成为detached状态的对象。

    2. Session级别缓存(一级缓存)、SessionFactory级别缓存(二级缓存)
    一级缓存处于session级别,只能够被当前的session使用,当你的session关闭之后,这些缓存被清除掉。你对一级缓存不能进行多少控制,例如最大缓存多少个对象等。二级缓存在SessionFactory级别,这意味着从这个SessionFactory创建的所有session对象能共享这个缓存。二级缓存允许更多的控制,例如设定一个最大缓存的对象数量,以防止缓存使用过多的内存;针对每个实体可以配置缓存策略。
    NHibernate提供很多方式操纵实体和数据库,这给缓存与数据库之间的一致性带来问题,你需要了解这些问题,在程序面避免这种一致性问题发生,或者保证它是在你的控制之内。举一个例子,假如你通过session.Get()方法获取了一个对象,这时在二级缓存中该对象被缓存,然后在另外的地方有人使用Native SQL在数据库中把这条记录删除了。这种情况下,二级缓存中该对象仍然是有效的,别人在使用session.Get()获取这个对象时NHibernate会返回二级缓存中的对象,但是在数据库中这个对象已经不存在了!

    另外是关于批量操作的问题。
    首先是批量插入、更新。一级缓存没有最大容量限制,所有persistent状态的对象都被缓存在一级缓存中,修改更新被记录下来,只在commit transaction的时候,才将更新提交数据库,在session关闭的时候清除一级缓存。假如你一次批量插入、更新10万、100万的对象,过大的缓存会导致大量的内存占用、低下的性能表现。可以使用下面的措施做一些改善:例如每500个对象执行一次应用到数据库和清除缓存的操作:
session.Flush();   //将缓存中的变化应用到数据库
session.Clear();   //清除当前session的缓存    使用batch-size使NHibernate一次提交多个SQL语句,在性能上会有一定的改善。方法是在批量操作的对象映射配置中将batch-size设置为50、100等。
    其次是关于批量删除操作。如果你使用
int deletedRows = session.Delete("from PlantItem");    NHibernate用下面的方式实现
IList list = session.CreateQuery("from PlantItem").List();
for (int i = 0; i 
页: [1]
查看完整版本: NHibernate考察系列 06 进阶篇