博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Hibernate 优化策略
阅读量:6989 次
发布时间:2019-06-27

本文共 2909 字,大约阅读时间需要 9 分钟。

hot3.png

最近需要对项目的持久层进行优化,阅读了《深入浅出Hibernate》其中提出的提高性能方案总结如下:
  1. DAO层与业务层独立;

  2. 使用最新版Hibernate;

  3. 设定合理的批处理参数(batch_size);

  4. 尽量使用延迟加载特性;

  5. 采用合理的Session管理机制;

  6. 制定合理的缓存策略;

Session控制

为了避免session创建的开销,需要对session的创建进行控制。 控制方法1)使用ThreadLocal的方式控制session的创建。2)并且使用filter的方式创建和关闭session,这样一个用户操作只需要使用一个Session。但需要对Session的开关进行良好的管理。 

延迟加载

lazy_load,所有有关数据关联(一对多,多对多等)的映射都需要指定延迟加载。因为当前系统的session关闭是在filter里面做的,所以不需要控制关联对象的加载。在特殊的情况下,比如session关闭后获取关联对象,可以在session关闭前调用Hibernate.initialize()API获取关联对象。 

事务控制

针对hibernate由三种dao操作 find save flush, find即查询不需要开事务,所以可以考虑针对查询不使用事务控制。针对saveOrUpdate使用事务, 现在事务提交是在filter结束的时候去做,但有一些action中是不需要事务的,频繁开关事务可能会带来一定的系统开销。 

事务的开关最好限定在方法内部,可以考虑在service方法中开关事务,可以避免这个问题。session关闭和事务提交的时候,hibernate会主动调用flush方法进行数据库同步。所以在当前项目中不需要关心flush方法。

事务实现选用和配置。使用jdbc事务控制. 不选用jta作为事务的实现。放弃理由, 当前测试服务器tomcat本身仅仅是个web server,并不支持jta。配置hibernate属性信息hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory           net.sf.hibernate.transaction.JDBCTransactionFactory

jta的好处:JTA提供了跨Session的事务管理能力,为以后扩展留下了选择空间。

实现单一的增删改操作不需要调用session.beginTransaction()等方法,针对多条记录的修改使用下面的方式调用api   UserTransaction ut = (UserTransaction)(new InitialContext(). lookup("java:comp/UserTransaction")); ut.begin();   //....     ut.commit();     

分页控制

 通过criteria. setFirstResult/setMaxResults方法可以限制一次查询返回的记录范围。 

缓存选用及配置管理
当前选用EHCache作为第二层的缓存(第一层为数据库缓存)。由于EHCache不支持分布式,所以将来可以考虑使用jgroup实现分布式。针对系统内大部分的dao操作使用只读(read)方式进行缓存。 需要写入的部署在不同的机器上解决多个jvm上数据不一致的问题。
 EHCache配置:首先配置hibernate缓存provider class属性hibernate.cache.provider_class net.sf.ehcache.hibernate.Provide。 配置ehcahe配置文件
<ehcache> 
       <diskStore path="java.io.tmpdir"/> 
       <defaultCache  maxElementsInMemory="10000"   //Cache中最大允许保存的数据数量 
           eternal="false"     //Cache中数据是否为常量 

           timeToIdleSeconds="120"   //缓存数据钝化时间 

           timeToLiveSeconds="120"   //缓存数据的生存时间 

          overflowToDisk="true"   //内存不足时,是否启用磁盘缓存 /> 
</ehcache> 
在hibernate映射文件中指定各个映射实体的Cache策略
   <cache usage="read-write"/>
   <cache usage="read-only"/>
 配置好Cache之后,Hibernate在运行期会自动应用Cache机制 

对于查询方法的选用策略

Query.list();  通过一条sql语句返回所有对象

Query.iterate(); 而iterate方法,则是首先通过一条Select SQL获取所有符合查询条件的记录的id。再对这个id集合进行循环操作,通过单独的Select SQL取出每个id所对应的记录,之后填入POJO中返回。

list方法不会从缓存中读取数据,而iterator方法在返回id集合后,针对每一条记录会先到缓存中读取数据。综合以上,当前系统使用原则:1)少量的数据和不频繁访问的数据使用list方法。2)频繁访问的数据使用iterator方法。 

数据库连接池配置和管理

 出于通用的原则选用dbcp,hibernate中的配置

  #hibernate.dbcp.maxActive 100

  #hibernate.dbcp.whenExhaustedAction 1

  #hibernate.dbcp.maxWait 120000

  #hibernate.dbcp.maxIdle 10

  ## prepared statement cache

  #hibernate.dbcp.ps.maxActive 100

  #hibernate.dbcp.ps.whenExhaustedAction 1

  #hibernate.dbcp.ps.maxWait 120000

  #hibernate.dbcp.ps.maxIdle 10

 其他配置

  hibernate.cache.use_query_cache

  cache.use_minimal_puts false

其他问题

1)  当获取大量关联数据的时候,需要指定关联集合属性 (解决N+1 Select问题)。

2)  batch-size (可选,默认是1) 指定一个用于根据标识符抓取实例时使用的"batch size"(批次抓取数量)可设置为10。

3)  对于一些统计查询,尽可能使用hql,而不要依赖于映射进行获取。

4)  对于代码级别的特殊查询,通过设置FetchMode提高效率。

5)  使用绑定变量,在查询中,使用占位符号: 替换非常量值,在查询中使用命名参数。因为query是可以缓存的,所以使用命名参数的方式可以提升查询效率。

转载于:https://my.oschina.net/sniperLi/blog/482903

你可能感兴趣的文章
给GRUB中的菜单加入密码。
查看>>
保留原有插件,快速升级Eclipse发行版本
查看>>
7月第1周国内域名商TOP10:万网DNSPOD差距缩小
查看>>
debian配置sambd
查看>>
整理grep实战文本搜索过滤技巧
查看>>
Samba通过Openldap统一认证
查看>>
我的友情链接
查看>>
阿里云CDN技术掌舵人文景:相爱相杀一路狂奔的这十年
查看>>
运维工程师必备LVS_NAT && LVS_ DR配置
查看>>
Authentication token manipulation error
查看>>
解决了前些天安装ROR环境时候的一个遗留问题
查看>>
vim删除命令
查看>>
Openstack之网络操作篇
查看>>
观察者模式
查看>>
好程序员web前端分享WebSocket协议
查看>>
Cocos2d-x3.2 屏幕适配
查看>>
centos ip配置
查看>>
Python 3.3 print输出的变化
查看>>
Lync开发实例4—组织架构同步
查看>>
Linux bond 网卡绑定配置教程
查看>>