hibernate是建立在JDBC基础上的框架,但他有很多JDBC所无法比拟的性能优化技术。下面介绍几种优化策略。
1.使用dynamic-insert与dynamic-update
在class标签中使用该属性,可以设置hibernate动态的生成SQL语句,而不是在hibernate启动时就生成预设的SQL语句。
当其设置为true时,hibernate会根据实际需求设置新增或更新的字段,而不是所有的字段。
<class name="com.hibernate.book" table="BOOK" dynamic-insert="true" dynamic-update="true">
2.延迟加载
为了避免在关联查询中带来无谓的开销而使用,即尽在需要读取数据库时才查询数据库。session的load()方法采用了,get()则没有。
(1)持久化对象的延迟加载
配置:
<class name="com.hibernate.Category" table="CATEGORY" lazy="true">
下述操作不会输出任何sql语句:
Category category= (Category) session.load(Category.class, new Integer(1));
tx.commit();
注:
load()方法获取的不是真正的持久化对象,而是一个代理对象(包含目标对象的属性和方法)。代理对象仅需要得到持久化类对象的引用,不需要获取所有属性值。
为顺利生成代理对象,hibernate的持久化类必须有公开的构造方法,不能声明为final。
(2)集合对象的延迟加载
地位:是延迟加载最重要的部分可以大幅度提高性能。
配置:
<class name="com.hibernate.Category" table="CATEGORY" lazy="true">
<set name="products" cascade="save-update" inverse="true" lazy="false">
.....</set>
</class>
下面操作不会查询product表的值:
Category category= (Category) session.load(Category.class, new Integer(1));
System.out.println(category.getName());tx.commit();
注:
product集合设置lazy=‘extra‘后,调用product的size(), contains(), 和isEmpty()方法不会引发不必要的查询。
(3)属性的延迟加载
一些数据库表有大数据字段类型(blob,clob),但其使用麻烦,且大多数情况下对提高性能有限。
(4)延迟加载出现的违例问题
使用hibernate.initialize():在session关闭之前强制加载被关联的对象。
使用open session in view设计模式。
3. 集合对象的抓取策略
概念:指hibernate在读取关联对象时所采取的策略。
(1)查询抓取(select fetching):先通过一个sql语句查询持久化对象,再通过另一个查询语句查询关联的对象。设置该策略后仍可使用HQL或者Criteria对象重载抓取策略。
(2)子查询抓取(Subselect fetching):先通过一个sql语句查询持久化对象,再通过另一个子查询语句查询关联的对象。
(3)链接抓取(join fetching):使用外连接语句获取当前对象或者相关的对象。不会对使用HQL语句的查询生效,只对其他查询方式如:session.get(),criteria.list()有效。
(4)批量查询(Batch fetching):先通过查询获取一个主键或外键列表,再使用单条语句获取对象。hibernate在查询时会按照设置的数值分批查询数据。
4. hibernate的“1+N”问题
场景1:
Query对象的iterate()方法获取查询数据。当代码第一次使用iterate()方法时,hibernate会先获取id列表值,再通过N条语句获取数据并添加到缓存中。
若Query对象的iterate()方法总不能很好地命中缓存数据时,将大大影响其性能,此时可以采用list()方法;反之,若可以很好地命中缓存,则可很好地提高性能。
场景2:
一对多,在一方查找得到了n个对象, 那么又需要将n个对象关联的集合取出,于是本来的一条sql查询变成了n+1条 。
多对一,在多方查询得到了m个对象,那么也会将m个对象对应的1方的对象取出, 也变成了m+1。
解决:
(1)使用延迟加载,只有当需要关联对象(访问其属性,非id字段)时才会发生查询动作。
(2)采用二级缓存, 即使第一次查询很慢,之后命中缓存也是很快的。
注:本文参考《Hibernate开发与实战》 刘伟 张利国 电子工业出版社 一书