在Hibernate中,存取数据需要网络通信,数据需要打包 ,解包,消耗资源很厉害
如果读取一个数据,后来又来一个请求读取这个数据,这里就可以运用一个缓存机制,将经常要读取的信息进行缓存。
例子:
第一次读取一个用户信息,读取之后放入一个map
第二次读取同一个信息,如果map中不为空,然后就从map中取
如果要更新,就先更新数据库里的,然后将缓存当中的remove掉
Hibernate缓存原理解析
Hibernate有两级缓存
一级缓存 Session级别的
第一次查询数据后,数据放入session中的缓存中,随着session的关闭,缓存就消失了。
限制:session关闭,缓存关闭
save update get load list iterate lock 都会将数据放入一级缓存中,一级缓存不能控制缓存的数量,所以数据量大的时候注意内存溢出,可以调用evict clear 方法清除缓存
从缓存中取:
get load
不能从缓存中取:
query criteria
query criteria
二级缓存 SessionFactory共享级
Hibernate二级缓存是交给第三方实现的,二级缓存可以在session关闭以后使用
可以在配置文件中配置二级缓存的实现
1打开二级缓存:
#hibernate.cache.use_second_level_cache false 配置二级缓存是否打开 缺省是打开的
2设置实现:
配置 二级缓存的实现提供者:参数 hibernate.cache.provider_class:
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider (Hibernate内部实现,健壮性不够)
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider(这种方法使用居多,可以webWork是一个公司制造的)
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider (Hibernate内部实现,健壮性不够)
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider(这种方法使用居多,可以webWork是一个公司制造的)
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
OScache:
Oscache 有单独的一个配置文件:在hibernate.jar etc 中有个OSCache配置文件
Oscache 有单独的一个配置文件:在hibernate.jar etc 中有个OSCache配置文件
cache.capacity=1000 缓存容量
支持集群缓存:
# JAVAGROUPS CLUSTER PROPERTIES
#
# Configuration properites for the JavaGroups clustering. Only one of these
# should be specified. Default values (as shown below) will be used if niether
# property is set. See the clustering documentation and the JavaGroups project
# (www.javagroups.com) for more information on these settings.
#
#cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;mcast_send_buf_size=150000;mcast_recv_buf_size=80000):PING(timeout=2000;num_initial_members=3):MERGE2(min_interval=5000;max_interval=10000):FD_SOCK:VERIFY_SUSPECT(timeout=1500):pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):pbcast.STABLE(desired_avg_gossip=20000):UNICAST(timeout=5000):FRAG(frag_size=8096;down_thread=false;up_thread=false):pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
#cache.cluster.multicast.ip=231.12.21.132
#
# Configuration properites for the JavaGroups clustering. Only one of these
# should be specified. Default values (as shown below) will be used if niether
# property is set. See the clustering documentation and the JavaGroups project
# (www.javagroups.com) for more information on these settings.
#
#cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;mcast_send_buf_size=150000;mcast_recv_buf_size=80000):PING(timeout=2000;num_initial_members=3):MERGE2(min_interval=5000;max_interval=10000):FD_SOCK:VERIFY_SUSPECT(timeout=1500):pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):pbcast.STABLE(desired_avg_gossip=20000):UNICAST(timeout=5000):FRAG(frag_size=8096;down_thread=false;up_thread=false):pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
#cache.cluster.multicast.ip=231.12.21.132
可以通过这个配置需要广播的UDP 然后通知分布式缓存的所有更新
第一种缓存:分布式缓存,每台机器都有相同的缓存数据
缺点:更新的时候成本很高
第二种方式:中央缓存
只专门设置一台机器进行缓存
缺点:取数据的时候,都要通过网络那台特定的机器去查找缓存的数据,成本较高 存数据更新数据成本低
优点:不会浪费空间
使用中央缓存和分布式缓存条件:
1读取大于修改
2数据量不能超过内存容量
3对数据要有独享的控制
4可以容忍无效的数据
3需要缓存的对象(修改不平凡,查询平凡的)
第一种方式:
<class-cache usage="read-only" class="com.coffee.beans.Employee"/>
类需要全名称
策略usage=""
read-only 只读 效率最高 适用于类不用修改
read write 需要修改的类,可以保证并发修改的正确性
nonstrict read write 非严格读写 不保证并发修改正确性,觉得并发修改错了也无所谓可以使用这个
transactional 事务性缓存,Jboss实现过
第二种方式:
在映射文件的id前配置
<hibernate-mapping package="com.coffee.one2one">
<class name="IdCard" table="id_card">
<cache usage="read-only"/>
<id name="id">
<class name="IdCard" table="id_card">
<cache usage="read-only"/>
<id name="id">
.......
通过以上3步,二级缓存就已经生效了。
其他设置:
hibernate.properties
打开统计信息
## generate statistics
#hibernate.generate_statistics true
#hibernate.generate_statistics true
使用方式:
SessionFactory中有一个方法:
Statistics s = getStatistic():
可以看到
sessionFactory初始化时间
session打开关闭次数
事务成功次数
乐观锁
链接打开关闭次数
二级缓存放入次数
二级缓存命中次数
二级缓存未命中次数
实体变化信息
etc
也可以调用其他方法单独获取个别信息
Hibernate 中一级缓存优先级高于二级缓存,先从一级缓存中查找,找不到再查找二级缓存,二级缓存没有就查找数据库
二级缓存性能指标:
命中率:查到到的次数,比上总的查找数
二级缓存的放入:
session.save 这种方式不适合主键生成策略中的native
sessison.update list get load iterator
Query Criteria :没有放入一级缓存,可以放入二级缓存(二级缓存缺省打开),但是命中率比较低
也可以打开,放入一级缓存:
#hibernate.cache.use_query_cache true
query.setCacheable();
Query 缓存原理:
如:Query q = session.createQuery(from Users where size >10 )
list <User> users = q.list();=
然后理解为把users放入二级缓存
二级缓存可以简单的看为一个map
所以就把这个条件作为key 把符合条件的对象集合的UserIds list<Integer>集合 作为value
再次查询的时候:
Query q = session.createQuery(from Users where size >10 )
就从缓存中get
二级缓存的获取:
get
load
iterator: N+1问题
二级缓存的清理:
SessionFactory.evictXXX();
SessionFactory.evictXXX();
如:evicit(User.class);
evict(id);