Hibernate 性能优化及缓存的使用


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级别的缓存)和查询缓存;hibernate还存在一种三级缓存即查询缓存,查询缓存依赖于二级缓存,所以使用三级缓存必须开启二级缓存,对于查询的结果集可以保存到查询缓存,下次使用不用去数据库找。

     一级缓存:

     

		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语句,说明第一次查询后,数据已被保持在二级缓存;


    hibernate的三级缓存(查询缓存):

    三级缓存用来缓存一些查询结果集,例如lquery的ist()方法,它查询的结果不能保持到二级缓存,可以保持到三级缓存中;

    1 配置好二级缓存,查询缓存依赖二级缓存;

    2 在配置文件中开启查询缓存; <property name="cache.use_query_cache">true</property>

    3 session获取的Query调用其他方法前先调用setCacheable(true)方法


   测试类

package com.tem.test;

import java.util.Iterator;
import java.util.List;

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();
		List<Classes> is=session.createQuery("from Classes c").setCacheable(true).list();
		session.getTransaction().commit();	
		session.close();
		
		Session session1=sf.openSession();
		session1.beginTransaction();
		List<Classes> is1=session1.createQuery("from Classes c ").setCacheable(true).list();		
		session1.getTransaction().commit();
		session1.close();
	}

}

两次查询,只发出了一条sql说明用到了查询缓存;




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值