1 clear()方法的运用:
由于hibernate在查询出来数据之后,会把数据进行缓存,对于同一个session多次大数据的查询,由于缓存会占用一定的内存空间,因此要多用seesion.clear(0方法清空缓存;
2 对于多发的sql语句合理设置tetch:
在关联查询时候,有时候只查询其中一个表里的数据,而hibernate会发出多条sql语句把另外一张表的数据也进行查询,影响性能,可以通过设置fetch的值来进行关联查询时候的懒加载;例如在多对一查询时候 @ManyToOne(cascade=(CascadeType.ALL),fetch=FetchType.LAZY) ;
3 Query的list()和Iterator()方法对比:
list()方法一次查询出全部对象;
Iterator()方法先查询出全部Id,再根据ID作为条件,一次查询一个对象,直到全部查完;
4 合理使用对象属性的懒加载以及load方法;
5 hibernate的缓存机制:
缓存是在内存中开辟一块空间,用来存储数据的,下次再次查找同样的数据,先在缓存中查找,查找不到再查询数据库。hibernate的缓存分为三种:一级缓存(session级别的缓存),二级缓存(SessionFactory级别的缓存)和查询缓存;
一级缓存:
Configuration cfg=new AnnotationConfiguration().configure(); SessionFactory sf=cfg.buildSessionFactory(); Session session=sf.openSession(); session.beginTransaction(); Student s1=(Student) session.load(Student.class, 1); System.out.println(s1.getSname()); // session.clear(); Student s2=(Student) session.load(Student.class, 1); System.out.println(s2.getSname()); session.getTransaction().commit(); session.close();
两个查询,只发送了一条sql语句,说明第一次查询出来已经将Student缓存到一级缓存中,下次查找从缓存取已经存在,不再发送sql语句;
多个session不能共用一个一级缓存,一级缓存不能跨越session,必须同一个session里才能使用;
二级缓存:
说明:
Hibernate自己没有二级缓存,需要借助其他厂商提供的缓存,默认使用的一种缓存是EHCache;
二级缓存是SessionFactory级别的,可以跨越session,通常放置一些 修改不频繁,经常访问的少量数据;
使用:
1 导入两个所需要的包:EhCache包 ehcache-1.2.3.jar 和 Ehcache使用 的日子包,为阿帕奇的日志包 commons-logging-1.1.1.jar;
2 在配置文件中开启二级缓存,指定二级缓存供应商,加入如下两句配置;
<property name="cache.use_second_level_cache">true</property> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
3 在要使用二级缓存的持久化类中加入注解(用xml配置的方式需要在映射文件中加配置,这里是使用注解的方式),有一个注意的地方,在多对一情况下多的一方存入缓存的时候,多的一方进行配置二级缓存的注解,一的一方也要加入该注解,否则不会使用二级缓存;在一的一方用二级缓存的时候,多的一方可以不用加注解;需要加入的注解是:@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 位置在类的上面
4 配置二级缓存配置文件 ehcache.xml,放在classPath根目录下;
持久化类:
package com.tem.hib; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Cache(usage=CacheConcurrencyStrategy.READ_ONLY) public class Classes { @Id @GeneratedValue private Integer cid; private String cname; @OneToMany(cascade=(CascadeType.ALL),mappedBy="classes") private Set<Student> students=new HashSet<Student>(); public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
package com.tem.hib; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity //@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) public class Student { @Id @GeneratedValue private Integer sid; private String sname; @ManyToOne(cascade=(CascadeType.ALL)) private Classes classes; public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } }
hibernate配置文件:
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:XE</property> <property name="connection.username">orcl</property> <property name="connection.password">newsnews</property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thread</property> <property name="cache.use_second_level_cache">true</property> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">update</property> <!-- <mapping resource="com/tem/hib/Student.hbm.xml"/> --> <mapping class="com.tem.hib.Classes" /> <mapping class="com.tem.hib.Student" /> <!-- <mapping class="com.tem.hib.Teacher" /> --> </session-factory> </hibernate-configuration>
二级缓存配置文件
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <ehcache> <!-- Sets the path to the directory where cache .data files are created. If the path is a Java System Property it is replaced by its value in the running VM. The following properties are translated: user.home - User's home directory user.dir - User's current working directory java.io.tmpdir - Default temp file path --> <diskStore path="java.io.tmpdir"/> <!--Default Cache configuration. These will applied to caches programmatically created through the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <!--Predefined caches. Add your cache configuration settings here. If you do not have a configuration for your cache a WARNING will be issued when the CacheManager starts The following attributes are required for defaultCache: name - Sets the name of the cache. This is used to identify the cache. It must be unique. maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <!-- Sample cache named sampleCache1 This cache contains a maximum in memory of 10000 elements, and will expire an element if it is idle for more than 5 minutes and lives for more than 10 minutes. If there are more than 10000 elements it will overflow to the disk cache, which in this configuration will go to wherever java.io.tmp is defined on your system. On a standard Linux system this will be /tmp" --> <cache name="sampleCache1" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <!-- Sample cache named sampleCache2 This cache contains 1000 elements. Elements will always be held in memory. They are not expired. --> <cache name="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> --> <!-- Place configuration for your caches following --> </ehcache>
测试类:
package com.tem.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import com.tem.hib.Classes; public class Test { public static void main(String[] args) { Configuration cfg=new AnnotationConfiguration().configure(); SessionFactory sf=cfg.buildSessionFactory(); Session session=sf.openSession(); session.beginTransaction(); Classes s1=(Classes) session.load(Classes.class, 2); System.out.println(s1.getCname()); session.getTransaction().commit(); session.close(); Session session1=sf.openSession(); session1.beginTransaction(); Classes s2=(Classes) session1.load(Classes.class, 2); System.out.println(s2.getCname()); session1.getTransaction().commit(); session1.close(); } }
输出结果:
两个session只发送了一条sql语句,说明第一次查询后,数据已被保持在二级缓存;