CSocket通信 2009-06-17
Hibernate脏数据检查
何谓脏数据(Dirty Data)?
这里的"脏"可能有些误解,脏数据并不是说非废弃或者无用的数据,而是指一个数据对象所携带的信息发生了改变之后的状态. 事务提交时,HIbernate会对Session中的PO进行检测,判断那些发生了变化,并装发生变化的数据更新到数据库中.
Hibernate脏数据的检查一般策略大致有下面两种:
数据对象监控
数据对象监控的实现方式,大体上是通过拦截器对数据对象的设值方法(setter)进行拦截,拦截器的实现可以借助Dynamic Proxy或者CGlib实现.一旦数据对象的设置方法被调用(通常这也意味着数据对象的内容发生变化),则将其标志为"待更新"状态,之后在数据库操作时将其更新到对应的库表.
数据版本比较
在持久层框架中维持数据对象的最近读取版本,当数据提交时数据与些版本进行比对 时,如果发生变化则将期同步到数据库相应的库Hibernate采取的是第二种检查策略
Hibernate数据缓存
Hibernate数据缓存是数据库数据在内存中的临时容器,它包含了库表数据在内存中的临时拷贝,位于数据库与数据访问层之间,缓存(Cache)往往是提升系统性能的关键因素.
数据缓存策略
ORM数据缓存应包含以下几个层次的内容:
◆事务级缓存(Transaction Layer Cache)
◆应用级/进程级缓存(Application/Process Layer Cache)
◆分布式缓存(Cluster Layer Cache)
事务级缓存
这里的事务可能是一个数据库事务,也可能是某个应用级事务.对于Hibernate而言,事务级缓存是基于Session生命周期实现的.每个Session会在内部维持一个数据缓存,此缓存随着Session的创建(销毁)而存在(消亡),因此也叫Session Level Cache(也称内部缓存)
应用级缓存
此缓存可由多个事务(数据事务或者应用级事务)共享,事务之间的缓存共享策略与应用的事务隔离机制密切相关.在Hibernate中,应用级缓存在SessionFactory层实现,所有由此SessionFactory创建的Session实例共享此缓存,因此也称为SessionFactory Level Cache.
分布式缓存
分布式缓存由多个应用级缓存实例组成集群,通过某种远程机制(如RMI或JMS)实现各个缓存实例间的数据同步,任何一个实例的数据修改操作,将导致整个集群间的数据状态同步.
需要注意的是,如果当前的应用与其他应用共享数据库,也就是说,在当前应用过程中,其他应用可能同时更新数据库,那么缓存策略的制定就需要格外小心了,这种情况下,一般采取一些保守策略可能会更加稳妥.
Hibernate数据缓存
以Hibernate主义加以区分,Hibernate数据缓存可分为以下两个层次:
◆内部缓存(Session Level,也称一级缓存)
◆二级缓存(SessionFactory Level,也称为二级缓存)
Hibernate中,缓存将在以下情况中发挥作用:
通过主键id加载数据.这包括根据id查询数据的Session.load方法,以及Session.iterate等 批量查询方法(Session.iterate进行查询时,也是根据id在缓存 中查找数据,类似一个Session.load循环).
延迟加载
Session在内部维护了一个Map数据类型,些数据类型中保持了所有与当前Session相关联对象. 内部缓存正常情况下由Hibernate自动维护,如果需要手动干预,我们可以通过以下方法完成:
◆Session.evict,将某个特定的对象从内部缓存中清除
◆Session.clear,清空内部缓存
二级缓存
在引入二级缓存时,应该考虑以下问题:
◆数据库是否与其他应用共享
◆应用是否需要部署在集群环境中.
如果满足以下条件,将纳入缓存管理:
◆数据不会被第三方应用修改
◆数据大小(Data Size)在可接受的范围之内.
◆数据更新频率较低
◆同一数据可能会被系统频繁引用.
◆非关键数据(关键数据,如金融帐户数据)。
第三方缓存实现
Hibernate本身并未提供二级缓存的产品化实现,而是为众多的第三方缓存组件提供了接入接口,较常用的第三方组件有:
1. JCS2. EHCache3. OSCache4. JBossCache5. SwarmCacheHibernate中启用二级缓存,需要在hibernate.cfg.xml配置hibernate.cache.provider_class参数,之后,需要在映射文件中指定各个映射实体(以及collection)的缓存同步策略。Hibernate提供了一下4种内置的缓存同步策略:1. read-only只读。对于不会发生改变的数据,可使用只读型缓存。