`
kidiaoer
  • 浏览: 821935 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

hibernate事务,一级缓存,二级缓存

阅读更多
hibernate主要从以下几个方面来优化查询性能:
  1,降低访问数据库的频率,减少select语句的数目,实现手段有:使用迫切左外连接或迫切内连接;对延迟检索或立即检索设置批量检索数目;使用查询缓存。

  2,避免加载多余的应用程序不需要访问的数据,实现手段有:使用延迟加载策略;使用集合过滤。

  3,避免报表查询数据占用缓存,实现手段为利用投影查询功能,查询出实体的部分属性。

  4,减少select语句中的字段,从而降低访问数据库的数据量,实现手段为利用Query的iterate()方法。

  Query的iterate()方法首先检索ID字段,然后根据ID字段到hibernate的第一级缓存以及第二级缓存中查找匹配的 Customer对象,如果存在,就直接把它加入到查询结果集中,否则就执行额外的select语句,根据ID字段到数据库中检索该对象。

  Query query = session.createQuery("from Customer where age<30");

  Iterator result = query.iterate();

  对于经常使用的查询语句,如果启用了查询缓存,当第一次执行查询语句时,hibernate会把查询结果存放在第二级缓存中,以后再次执行该查询语句时,只需从缓存中获得查询结果,从而提高查询性能。如果查询结果中包含实体,第二级缓存只会存放实体的OID,而对于投影查询,第二级缓存会存放所有的数据值。

  查询缓存适用于以下场合:在应用程序运行时经常使用的查询语句;很少对与查询语句关联的数据库数据进行插入,删除,更新操作。

  对查询语句启用查询缓存的步骤如下:

  1,配置第二级缓存。

  2,在hibernate的配置文件中设置查询缓存属性:hibernate.cache.use_query_cache=true

  3,即使设置了缓存,在执行查询语句时仍然不会启用查询缓存,只有在调用query.setCacheable()后才启用缓存:

  Query query = session.createQuery("from Customer c where c.age > :age");

  query.setInteger("age", age):

  query.setCacheable(true);

  如果希望更加精粒度地控制查询缓存,可以设置缓存区域:query.setCacheRegion("customerQueries");

  hibernate提供了3种和查询相关的缓存区域:

  1,默认的查询缓存区域:net.sf.hibernate.cache.StandardQueryCache。

  2,用户自定义的查询缓存区域:如customerQueries。

  3,时间戳缓存区域:net.sf.hibernate.cache.UpdateTimestampCache。

  默认的查询缓存区域以及用户自定义的查询缓存区域都用于存放查询结果,而时间戳缓存区域存放了对于查询结果相关的表进行插入,更新,删除操作的时间戳。hibernate通过时间戳缓存区域来判断被缓存的查询结果是否过期。当应用进程对数据库的相关数据做了修改,hibernate会自动刷新缓存的查询结果。但是如果其它应用进程对数据库的相关数据做了修改,hibernate无法监测到这一变化,此时必须由应用程序负责监测这一变化(如通过发送和接收事件或消息机制),然后手工刷新查询结果。

  Query.setForceCacheRefresh(true)方法允许手工刷新查询结果,它使得hibernate丢弃查询缓存区域中己有的查询结果,重新到数据库中查询数据,再把查询结果存放在查询缓存区域中。

  一个session可以和多个事务对应:

  Transaction trans1 = session.beginTransaction();

  ... ...//数据库操作

  trans1.commit();//提交第一个事务

  session.disconnect();//释放数据库连接

  ... ...//执行一些耗时的操作,这段操作不属于任何事务

  session.reconnect();//重新获取数据库连接

  Transaction trans2 = session.beginTransaction();//开始第二个事务

  ... ...//数据库操作

  trans2.commit();//提交第二个事务

  注意:如果在执行session的一个事务时出现了异常,就必须立即关闭这个session,不能再利用这个session来执行其它的事务。

  许多数据库系统都有自动管理锁的功能,它们能根据事务执行的SQL语句,自动在保证事务间的隔离性与保证事务间的并发性之间做出权衡,然后自动为数据库资源加上适当的锁,在运行期间还会自动升级锁的类型,以优化系统的性能。

  对于普通的并发性事务,通过系统的自动锁定管理机制基本可以保证事务之间的隔离性,但如果对数据安全,数据库完整性和一致性有特殊要求,也可以由事务本身来控制对数据资源的锁定和解锁。

  数据库系统能够锁定的资源包括:数据库,表,区域,页面,键值(指带有索引的行数据),行(即表中的单行数据)。在数据库系统中,一般都支持锁升级,以提高性能。

  按照封锁程序,锁可以分为:共享锁,独占锁,更新锁。

  共享锁:用于读数据操作,它是非独占的,允许其它事务同时读取其锁定的资源,但不允许其它事务更新它。

  独占锁:也称排它锁,适用于修改数据的场合,它所销定的资源,其它事务不能读取也不能修改。

  更新锁:在更新操作的初始化阶段用来锁定可能要被修改的资源,这可以避免使用共享锁造成的死锁现象。

  许多的数据库系统能够自动定期搜索和处理死锁问题,当检测到锁定请求环时,系统将结束死锁优先级最低的事务,并且撤销该事务。

  应用程序中可以采用下面的一些方法尽量避免死锁:

  1,合理安排表访问顺序;

  2,使用短事务;

  3,如果对数据的一致性要求不高,可以允许脏读,脏读不需要对数据资源加锁,可以避免冲突;

  4,如果可能的话,错开多个事务访问相同数据资源的时间,以防止锁冲突。

  5,使用尽可能低的事务隔离级别。

  为了实现短事务,在应用程序中可以考虑使用以下策略:

  1,如果可能的话,尝试把大的事务分解为多个小的事务,然后分别执行,这保证每个小事务都很快完成,不会对数据资源锁定很长时间。

  2,应该在处理事务之前就准备好用户必须提供的数据,不应该在执行事务过程中,停下来长时间等待输入数据。

  数据库系统提供了四种事务隔离级别供用户选择:

  1,Serializable:串行化。

  2,Repeatable Read:可重复读。

  3,Read Commited:读己提交数据。

  4,Read Uncommited:读未提交数据。

  隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先把数据库系统的隔离级别设为 ReadCommited,它能够避免脏读,而且具有较好的并发性能,尽管它会导致不可重复读,虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。


JDBC数据库连接使用数据库系统默认的隔离级别,在hibernate的配置文件中可以显式地设置隔离级别 (hibernate.connection.isolation=2),每一种隔离级别都对应一个整数。

  1:Read Uncommitted;

  2:Read Committed;

  4:Repeatable Read;

  8:Serializable

  在受管理的环境中,如果hibernate使用的是数据库连接来自于应用服务器提供的数据源,hibernate不会修改这些连接的事务隔离级别,在这种情况下,应该通过修改应用服务器的数据源配置来修改隔离级别。

  悲观锁:指在应用程序中显式地为数据资源加锁,先锁定资源再进行操作,尽管悲观锁能够防止丢失更新和不可重复读这类并发问题,但是它会影响并发性能,因此应该很谨慎地使用悲观锁。

  乐观锁:完全依靠数据库的隔离级别来自动管理锁的工作,应用程序采用版本控制手段来避免可能出现的并发问题。

  悲观锁有两种实现方式:1,在应用程序中显式指定采用数据库系统的独占锁来锁定数据资源;2,在数据库表中增加一个表明记录状态的LOCK字段,当它取值为Y时,表示该记录己经被某个事务锁定,如果为N,表明该记录处于空闲状态,事务可以访问它。

  以下select语句,指定采用独占锁来锁定查询的记录:select ... for update;执行该查询语句的事务持有这把锁,直到事务结束才会释放锁。

  hibernate可以采用如下方式声明使用悲观锁:Account account = (Account)session.get(Account.class, 1, LockMode.UPGRADE);

  net.sf.hibernate.LockMode类表示锁模式,它的取值如下:

  LockMode.NONE:默认值。先查缓存,缓存没有再去数据库中查。

  LockMode.READ:总是查询数据库,如果映射文件设置了版本元素,就执行版本比较。主要用于对一个游离对象进行版本检查。

  LockMode.UPGRADE:总是查询数据库,如果映射文件设置了版本元素,就执行版本比较。如果数据库支持悲观锁就执行.... for update。否则执行普通查询。

  LockMode.UPGRADE_NOWAIT:和UPGRADE功能一样,此外,对oracle数据库执行... for update nowait; nowait表明,如果不能立即获得悲观锁就抛出异常。

  LockMode.WRITE:当hibernate向数据库保存或更新一个对象时,会自动使用这种模式,它仅供hibernate内部使用,应用程序中不应该使用它。

  如果数据库不支持select ... for update语句,也可以由应用程序来实现悲观锁,这需要要表中增加一个锁字段lock。

  hibernate映射文件中的<version>和<timestamp>元素都具有版本控制功能。< version>利用一个递增的整数来跟踪数据库表中记录的版本,<timestamp>用时间戳来跟踪数据库表中记录的版本。

  version的用法如下:

  配置文件中:<version name="version" column="VERSION"/>必须紧跟在<id>元素的后面。数据库中的version(int)字段与version属性映射。

  应用程序无需为JavaBean的version属性显示赋值,在持久化JavaBean 对象时,hibernate会自动为它赋初始值0,在更新数据时,hibernate会更新自动version属性:update ACCOUNTS set NAME='Tom',BALANCE=1100,VERSION=1 where ID=1 and VERSION=0;

  如果在此过程中有其它程序操作过此记录,那么它的version就会有更新,再次执行update语句时会找不到匹配的记录,此时 hibernate会抛出StaleObjectStateException。在应用程序中应该处理这种异常,处理方法有两种:

  1,自动撤消事务,通知用户信息己被其它事务修改,需要重新开始事务。

  2,通知用户信息己被其它事务修改,显示最新数据,由用户决定如果继续。

  只有当hibernate通过update语句更新一个对象时,才会修改它的version属性,对于存在关联关系的对象,只更新发生变化的对象,对没有发生变化的关联对象是不会更新的,也就是说version不具有级联特性。

  timestamp用法如下:

  配置文件和表中各加一个属性(表中是timestamp类型):<timestamp name="lastUpdatedTime" column="LAST_UPDATED_TIME" />必须紧跟在<id>元素的后面。

  当持久化一个JavaBean对象时,hibernate会自动用当前的系统时间为lastUpdatedTime属性赋值,更新时也会用系统时间来更新此字段。理论上<version>元素比<timestamp>更安全一些,因为<timestamp> 只能精确到秒,不能处理毫秒内的同步。

  因此,建议使用基于整数的<version>元素。

  对游离对象进行版本检查,如果不一致,会抛出StaleObjectStateException()。:

  Transaction trans = session.beginTransaction();

  session.lock(account, LockMode.READ);//仅仅执行版本检查(与数据库中的最新数据进行比较),而不会保存数据库。

  trans.commit();

  如果数据库中不包含代表版本或时间戳的字段,hibernate提供了其它方法实现乐观锁,把<class>元素的 optimistic-lock属性设为all。把<class>元素的optimistic-lock属性设为all或dirty。必须同时把dynamic-update属性设为true。

  optimistic-lock=true时,hibernate更新时会在where子句中包含JavaBean对象被加载时的所有属性。

  optimistic-lock=dirty时,hibernate更新时会在where子句中仅包含被更新过的属性。

  尽管这种方法也能实现乐观锁,但是这种方法速度很慢,而且只适用于在同一个session中加载了该对象,然后又在同一个session中更新了此对象的场合。如果在不同的session中,会导致第二个session无法知道JavaBean对象被第一个session加载时所有属性的初始值,因此不能在update语句的where子句中包含JavaBean对象的属性的初始值,因此执行以下update语句:update ACCOUNTS set NAME='tom',BALANCE=900 where ID=1;这会导致当前事务覆盖其它事务对这条记录己做的更新。

  hibernate的二级缓存本身的实现很复杂,必须实现并发访问策略以及数据过期策略。SessionFactory的外置缓存是一个可配置的缓存插件,在默认情况下不会启用。

  二级缓存,进程范围或群集范围,会出现并发问题,对二级缓存可以设定以下四种类型的并发访问策略,每一种策略对应一种事务隔离级别。

  1,事务型:仅仅在受管理环境中适用,它提供Repeatable Read事务隔离级别,对于经常读但是很少写的数据,可以采用这种隔离级别,因为它可以防止脏读和不可重复读这类并发问题。

  2,读写型:提供Read Committed事务隔离级别,仅仅在非群集的环境中适用,对于经常读但是很少写的数据,可以采用这种隔离类型,因为它可以防止脏读这类并发问题。

  3,非严格读写型:不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而尽量避免脏读,对于极少被修改并且允许脏读的数据,可以采用这种并发访问策略。

  4,只读型:对于从来不会写的数据,可以使用这种并发访问策略。

  事务型策略的隔离级别最高,只读型的最低,事务隔离级别越高,并发性能越低,如果二级缓存中存放中的数据会经常被事务修改,就不得不提高缓存的事务隔离级别,但这又会降低并发性能,因此,只有符合以下条件的数据才适合于存放到二级缓存中:

  1,很少被修改;2,不是很重要的数据,允许偶尔出现并发问题;3,不会被并发访问的数据;4,参考数据;

  以下数据不适合于存放到二级缓存中:

  1,经常被修改的数据;2,财务数据,绝对不允许出现并发问题;3,与其它应用共享的数据;

  hibernate还为查询结果提供了一个查询缓存,它依赖于二级缓存。

  Session为应用程序提供了两个管理一缓存的方法:

  evict():从缓存中清除参数指定的持久化对象;如果在映射文件关联关系的cascade为all或all-delete-orphan 时,会级联清除;它适用于不希望session继续按照该对象的状态变化来同步更新数据库;在批量更新或指量删除的场合,当更新或删除一个对象后,及时释放该对象占用的内存;值得注意的是,批量更新或删除的最佳方式是直接通过JDBC API执行相关的SQL语句或者调用相关的存储过程。

  clear():清空缓存中所有持久化对象;

  在多数情况下,不提倡通过evict()和clear()方法来管理一级缓存,因为它们并不能显着地提高应用的性能,管理一级缓存的最有效的方法是采用合理的检索策略和检索方式,如通过延迟加载,集合过滤,投影查询等手段来节省内存开销。

  hibernate中直接通过JDBC API来执行更新或删除操作的方法如下:

  Transaction trans = session.beginTransaction();

  Connection conn = session.connection();

  PreparedStatement statement = conn.prepareStatement("update ACCOUNTS set AGE=AGE+1 where AGE>0");

  statement.executeUpdate();

  trans.commit();

  如果底层数据库支持存储过程,也可以直接调用存储过程来执行指量更新:

  Transaction trans = session.beginTransaction();

  Connection conn = session.connection();

  CallableStatement statement = conn.prepareCall("{call batchUpdateCustomer(?)}");

  statement.setInt(1, 0);//把第1个参数的值设为0

  statement.executeUpdate();

  trans.commit();

  hibernate中session的各种重载的update()方法一次都只能更新一个对象,而delete()方法有些重载形式允许以 HQL语句作为参数,如:

  session.delete("from Customer c where c.age>0");

  但是它并不是执行一条delete语句,而是把符合条件的数据先查找出来,再一个个地执行delete操作。


hibernate的二级缓存允许选用以下类型的缓存插件:

  1,EHCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,对hibernate的查询缓存提供了支持。

  2,OpenSymphony OSCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对hibernate的查询缓存提供了支持。

  3,SwarmCache:可作为群集范围内的缓存,但不支持hibernate的查询缓存。

  4,JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对hibernate的查询缓存提供了支持。

  下表列出了以上四种类型的缓存插件支持的并发访问策略:

  以面的四种缓存插件都是由第三方提供的。EHCache来自于hibernate开放源代码组织的另一个项目;JBossCache由 JBoss开放源代码组织提供;为了把这些缓存插件集成到hibernate中,hibernate提供了 net.sf.hibernate.cache.CacheProvider接口,它是缓存插件与hibernate之间的适配器。hibernate为以上缓存插件分别提供了内置的CacheProvider实现:

  net.sf.hibernate.cache.EhCacheProvider

  net.sf.hibernate.cache.OSCacheProvider

  net.sf.hibernate.cache.SwarmCacheProvider

  net.sf.hibernate.cache.TreeCacheProvider:JBossCache插件适配器。

  配置进程范围内的二级缓存主要包含以下步骤:

  1,选择需要使用二级缓存的持久化类。设置它的命名缓存的并发访问策略。hibernate既允许在分散的各个映射文件中为持久化类设置二级缓存,还允许在hibernate的配置文件hibernate.cfg.xml中集中设置二级缓存,后一种方式更有利于和缓存相关的配置代码的维护。示例如下:

  <hibernate-configuration>

  <session-factory>

  <property ... >

  <!-- 设置JBossCache适配器 -->

  <property name="cache.provider_class">net.sf.hibernate.cache.TreeCacheProvider</property>

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

  <mapping .../>

  <!-- 设置Category类的二级缓存的并发访问策略 -->

  <class-cache class="mypack.Category" usage="transaction" />

  <!-- 设置Category类的items集合的二级缓存的并发访问策略 -->

  <collection-cache collection="mypack.Category.items" usage="transactional" />

  <!-- 设置Item类的二级缓存的并发访问策略 -->

  <class-cache class="mypack.Item" usage="transactional" />

  </session-factory>

  </hibernate-configuration>

  cache.use_minimal_puts属性为true,表示hibernate会先检查对象是否己经存在于缓存中,只有当对象不在缓存中,才会向缓存加入该对象的散装数据,默认为false。对于群集范围的缓存,如果读缓存的系统开销比写缓存的系统开销小,可以将此属性设为true,从而提高访问缓存的性能,而对于进程范围内的缓存,此属性应该取默认值false。

  2,选择合适的缓存插件,每种插件都有自带的配置文件,因此需要手工编辑该配置文件,EHCache的配置文件为ehcache.xml,而 JBossCache的配置文件为treecache.xml。在配置文件中需要为每个命名缓存设置数据过期策略。

  hibernate允许在类和集合的粒度上设置二级缓存,在映射文件中,<class>和<set>元素都有一个 <cache>子元素,这个子元素用来配置二级缓存,例如以下代码把Category实例放入二级缓存中,采用读写并发访问策略:

  <class name="mypack.Category" talbe="CATEGORIES">

  <cache usage="read-write"/>

  <id ...>

  </id>

  ...

  </class>

  每当应用程序从其它对象导航到Category对象,或者从数据库中加载Category对象时,hibernate就会把这个对象放到第二级缓存中,<class>元素的<cache>子元素表明hibernate会缓存Category对象的简单属性的值,但是它并不会同时缓存Category对象的集合属性,如果希望缓存集合属性中的元素,必须在<set>元素中加入<cache>子元素:

  <set name="items" inverse="true" lazy="true">

  <cache usage="read-write" />

  <key ...>

  </set>

  当应用程序调用category.getItems().iterate()方法时,hibernate会把item集合中的元素存放到缓存中,此时hibernate仅仅把与Category关联的Item对象的OID存放到缓存中,如果希望把整个Item对象的散装数据存入缓存,应该在 Item.hbm.xml文件的<class>元素中加入<cache>子元素。

  EHCache缓存插件是理想的进程范围内的缓存实现。如果使用这种缓存插件,需要在hibernate的 hibernate.properties配置文件中指定EhCacheProvider适配器,代码如下:

  hibernate.cache.provider=net.sf.hibernate.cache.EhCacheProvider

  EHCache缓存有自己的配置文件,名为ehcache.xml,这个文件必须存放于应用的classpath中,下面是一个样例:

  <ehcache>

  <diskStore path="C:\\temp"/>

  <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"/>

  <cache name="mypack.Category" maxElementsInMemory="500" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false"/>

  <cache name="mypack.Category.items" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/>

  <cache name="mypack.Item" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/>

  </ehcache>

  hibernate软件包的etc目录下提供了ehcache.xml文件的样例,并且对于它的配置元素做了详细的说明。

  ehcache.xml目录下提供了ehcache.xml文件的样例,并且对它的配置元素做了详细的说明:

  <diskStore>:指定一个文件目录,当EHCache把数据写到硬盘上时,将把数据写到这个文件目录下。

  <defaultCache>:设定缓存的默认数据过期策略。

  <cache>:设定具体的命名缓存的数据过期策略。

  在映射文件中,对每个需要二级缓存的类和集合都做了单独的配置,与此对应,在ehcache.xml文件中通过<cache>元素来为每个需要二级缓存的类和集合设定缓存的数据过期策略。下面解释一下<cache>元素的各个属性的作用:

  name:设置缓存的名字,它的取值为类的完整名字或者类的集合的名字,如果name属性为mypack.Category,表示 Category类的二级缓存;如果name属性为mypack.Category.items,表示Category类的items集合的二级缓存。

  maxInMemory:设置基于内存的缓存可存放的对象的最大数目。

  eternal:如果为true,表示对象永远不会过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds 属性。默认为false。

  timeToIdleSeconds:设定允许对象处于空闲状态的最长时间,以秒为单位,当对象从最近一次被访问后,如果处于空闲状态的时间超过了指定的值,这个对象会过期,EHCache将把它从缓存中清除,只有当eternal属性为false,它才有效,值为0表示对象可以无限期地处于空闲状态。

  timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位,当对象自从被放入缓存中后,如果处于缓存中的时间超过了指定的值,这个对象就会过期,EHCache将把它从缓存中清除,只有当eternal属性为false,它才有效,值为0表示对象可以无限期地处于空闲状态。它的值必须大于或等于timeToIdleSeconds的值才有意义。

  overflowToDisk:如果为true,表示当基于内存的缓存中的对象数目达到了maxInMemory界限,会把溢出的对象写到基于硬盘的缓存中。

  每个命名缓存代表一个缓存区域,每个缓存区域有各自的数据过期策略,命名缓存机制使得用户能够在每个类以及类的每个集合的粒度上设置数据过期策略。

  EHCache适用于hibernate应用发布在单个机器中的场合。


在群集环境下,可以用JBossCache作为hibernate的二级缓存,它的配置步骤如下:

  1,在hibernate配置文件中设置JBossCache适配器,并且为需要使用二级缓存的类和集合设置缓存的并发访问策略。

  2,编辑JBossCache自身的配置文件,名为treecache.xml,这个文件必须放在classpath中,对于群集环境中的每个节点,都必须提供单独的treecache.xml文件,假如群集环境中有两个节点node A和node B,node A节点的名字为ClusterA,下面是node A节点的treecache.xml文件的样例:

  <?xml version="1.0" encoding="UTF-8"?>

  <server>

  <classpath codebase="./lib" archives="jboss-cache.jar,jgroups.jar"/>

  <!-- 把TreeCache发布为JBoss的一个JMX服务 -->

  <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">

  <depends>jboss:service=Naming</depends>

  <depends>jboss:service=TransactionManager</depends>

  <!-- TreeCache运行在群集环境的名为ClusterA的节点上 -->

  <attribute name="ClusterName">ClusterA</attribute>

  <!-- TreeCache采用同步通信机制 -->

  <attribute name="CacheMode">REPL_SYNC</attribute>

  <attribute name="SyncReplTimeout">10000</attribute>

  <attribute name="LockAcquisitionTimeout">15000</attribute>

  <attribute name="FetchStateOnStartup">true</attribute>

  <!-- TreeCache采用内置的数据过期策略:LRUPolicy -->

  <attribute name="EvictionPolicyClass">org.jboss.cache.eviction,LRUPolicy</attribute>

  <attribute name="EvictionPolicyConfig">

  <config>

  <attribute name="wakeUpIntervalSeconds">5</attribute>

  <!-- Cache wide default -->

  <region name="/_default_">

  <attribute name="maxNodes">5000</attribute>

  <attribute name="timeToIdleSeconds">1000</attribute>

  </region>

  <!-- 配置Category类的数据过期策略 -->

  <region name="/mypack/Category">

  <attribute name="maxNodes">500</attribute>

  <attribute name="timeToIdleSeconds">5000</attribute>

  </region>

  <!-- 配置Category类的items集合的数据过期策略 -->

  <region name="/mypack/Category/items">

  <attribute name="maxNodes">5000</attribute>

  <attribute name="timeToIdleSeconds">1800</attribute>

  </region>

  </config>

  </attribute>

  <!-- 配置JGroup -->

  <attribute name="ClusterConfig">

  <config>

  <UDP bind_addr="202.145.1.2" ip_mcast="true" loopback="false" />

  <PING timeout="2000" num_initial_members="3" up_thread="false" down_thread="false" />

  <FD_SOCK/>

  <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800" max_xmit_size="8192" up_thread="false" down_thread="false" />

  <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10" down_thread="false" />

  <pbcast.STABLE desired_avg_gossip="20000" up_thread="false" down_thread="false" />

  <FRAG frag_size="8192" down_thread="false" up_thread="false" />

  <pbcast.GMS join_timeout="5000" join_retry_timeout="2000" shun="true" print_local_addr="true" />

  <pbcast.STATE_TRANSFER up_thread="true" down_thread="true" />

  </config>

  </attribute>

  </mbean>

  </server>

  以上配置文件把JBossCache配置为JBoss的一个JMX服务,此外还配置了JGroup,它是一个通信库。JBoss为 JBossCache提供了几种实现,hibernate采用的是TreeCache实现。treecache.xml文件夹的开头几行是JBoss的 JMX服务的发布描述符,如果TreeCache不运行在JBoss服务器中,这几行会被忽略。

  TreeCache采用内置的org.jboss.cache.eviction.LRUPolicy策略,它是一种控制缓存中的数据过期的策略,由于当一个对象过期后,就会从缓存中清除,因此数据过期策略也叫做数据清除策略。接下来配置了Category类和它的items集合设置了具体的数据过期策略。

  最后配置了JGroup,它包含一系列通信协议,这些通信协议的次序很重要,不能随意修改它们。第一个协议为UDP,它和一个IP地址 202.145.1.1绑定,这是当前节点的IP地址,UDP协议使得该节点支持广播通信,如果节点选用的是微软的windows平台,必须把 loopback属性设为true。其它的JGroup属性很复杂,它们主要用于管理群集中节点之间的通信,想进一步了解,可以参考JBoss网站上的 JGroup文档。

  可以按照同样的方式配置node B节点的treecache.xml文件,只需修改其中UDP协议的IP绑定地址。

  通过以上配置,hibernate将启用群集范围内的事务型缓存,每当一个新的元素加入到一个节点的缓存中时,这个元素就会被复制到其它节点的缓存中,如果缓存中的一个元素被更新,那么它就会过期,并从缓存中清除。

  只有在hibernate的配置文件或映射文件中为一个持久化类设置了二级缓存,hibernate在加载这个类的实例时才会启用二级缓存。

  SessionFactory也提供了evict()方法用于从二级缓存中清除对象的散装数据,如:

  sessionFactory.evict(Category.class, 1);//清除二级缓存中OID为1的Category对象

  sessionFactory.evict("mypack.Category");//清除二级缓存中所有的Category对象

  sessionFactory.evictCollection("mypack.Category.items");//清除二级缓存中 Category类的所有对象的items集合


分享到:
评论

相关推荐

    hibernate一级缓存和二级缓存的区别与联系

    一级缓存是事务级别的,保证了数据的强一致性,而二级缓存提供了更多的灵活性,可以跨事务共享,但需要考虑并发访问策略以保证数据一致性。选择合适的缓存策略和范围对于优化应用性能至关重要。

    hibernate一级缓存、二级缓存和查询缓存

    **hibernate一级缓存、二级缓存和查询缓存** 在Java的持久化框架Hibernate中,缓存机制是提高应用程序性能的关键要素。缓存能够减少数据库的访问次数,提高数据读取速度,并且在一定程度上降低了系统的负载。本文将...

    hibernate的一级缓存和二级缓存

    《深入理解Hibernate的一级缓存与二级缓存》 Hibernate作为一款强大的ORM框架,其缓存机制是优化数据库操作性能的关键之一。缓存主要分为一级缓存和二级缓存,它们各自承担着不同的职责,共同提升了数据访问的效率...

    Hibernate一级缓存和二级缓存

    标题“Hibernate一级缓存和二级缓存”指的是Hibernate框架中的两种缓存机制,它们是提高数据访问性能的关键要素。一级缓存是Session级别的,而二级缓存是SessionFactory级别的,两者在数据库操作中起到了重要的作用...

    Hibernate一级缓存、二级缓存以及查询缓存实例

    本文将深入探讨Hibernate的一级缓存、二级缓存以及查询缓存,通过具体的实例来阐述它们的工作原理和使用方法。 首先,我们从一级缓存开始。一级缓存是Hibernate默认提供的缓存,它是每个Session级别的,也被称为...

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    本篇文章将深入探讨Hibernate的二级缓存机制,以及如何进行一级缓存与二级缓存的同步,同时还会介绍二级缓存的配置文件设置。 一级缓存是Hibernate默认提供的缓存,每个SessionFactory实例都有一个一级缓存。当对象...

    hibernate二级缓存

    Hibernate 二级缓存是一种高效的数据存储机制,它能够显著提升Web应用的性能,尤其是在处理大量数据流动时。缓存的主要目标是减少应用与数据库之间的交互次数,从而降低延迟并减轻数据库服务器的压力。在Hibernate...

    Hibernate 二级缓存 总结整理

    **Hibernate 二级缓存总结整理** 在Java的持久化框架中,Hibernate是一个广泛使用的ORM(对象关系映射)工具,它极大地简化了数据库操作。在处理大数据量或高并发的场景下,为了提高性能和减少数据库负载,...

    hibernate二级缓存java包下载

    二级缓存是 Hibernate 缓存策略的一部分,它在应用程序的多个会话之间共享数据,进一步优化了数据库访问效率。 二级缓存分为以下关键知识点: 1. **一级缓存与二级缓存的区别**: - 一级缓存:每个 Hibernate ...

    Hibernat一级缓存(源码)

    3. 分布式缓存:在多节点环境中,可以考虑使用二级缓存(如 Ehcache 或 Infinispan)来实现跨节点的数据共享,提高系统性能。 总结: 一级缓存作为 Hibernate 的核心特性,极大地提高了数据访问效率。通过对源码的...

    hibernate二级缓存(包括注解方式)

    1. **Hibernate二级缓存**:在默认情况下,Hibernate只使用一级缓存(Session级别的缓存),二级缓存则可由用户自定义配置。二级缓存是多个Session共享的,可以跨事务存储对象,提高了数据读取速度,减少了对数据库...

    Hibernate一级缓存和二级缓存【内附二级缓存数据存储结构】

    Hibernate作为Java领域中...总之,理解并熟练运用Hibernate的一级和二级缓存,对于优化Java应用程序的性能至关重要。通过合理配置和选择合适的缓存策略,我们可以有效地平衡性能和数据一致性,从而提高系统的整体效能。

    hibernate 二级缓存

    2. **写操作**:更新或删除操作后,Hibernate不仅会更新数据库,还会同步更新一级缓存和二级缓存中的数据,以保持一致性。 3. **查询优化**:在进行批量查询时,如果某个对象已经在二级缓存中,Hibernate会直接从...

    Hibernate_二级缓存总结

    在Hibernate框架中,缓存主要分为一级缓存和二级缓存。 **1. 一级缓存** 一级缓存是Session级别的,每个Session都有自己的缓存空间。当我们在Session内进行操作时,例如增删改查,这些操作的对象会被保存在一级缓存...

    模拟hibernate中一级缓存

    在实际开发中,可以结合二级缓存(如 Ehcache 或 Redis)进一步优化数据访问效率,实现更高效的缓存策略。 总结,Hibernate的一级缓存是提升应用程序性能的重要工具。它在Session内部提供了一种内存级别的缓存机制...

    hibernate二级缓存 SSH

    Hibernate二级缓存是一个优化策略,它能提高数据访问性能,减少对数据库的直接访问。 首先,Struts2作为MVC(模型-视图-控制器)框架,负责处理用户请求和转发到相应的业务逻辑。Spring框架则提供了依赖注入和事务...

    Hibernate_二级缓存 实验心得,手册

    而二级缓存则是在`SessionFactory`级别提供的缓存机制,它可以跨越多个`Session`和事务,是一种持久化的缓存策略。 #### 二、二级缓存的作用及实现 ##### 作用 - **提高性能**:减少数据库的访问次数,提高应用...

    Hibernatehibernate一级缓存.pdf

    在Java的持久化框架Hibernate中,一级缓存是其核心特性之一,它是Session级别的缓存,也称为事务级缓存。一级缓存的作用是提高数据访问效率,减少对数据库的直接访问,从而提升应用程序的性能。当我们在Hibernate中...

    Hibernate性能优化:一级缓存

    同时,理解一级缓存的原理也有助于我们理解二级缓存和其他缓存解决方案,如Ehcache和Infinispan,以及它们在复杂分布式系统中的应用。 总之,Hibernate的一级缓存是提高应用程序性能的关键因素之一。理解其工作原理...

Global site tag (gtag.js) - Google Analytics