缓存由ORM框架提供以便用户可以获得更快速的访问速度,同时框架本身也减少了数据库查询操作。hibernate同样在两个层上提供了缓存的功能。
一级缓存:这是在session范围内默认使用的,了解更多可以读这篇文章。
二级缓存:这是在一级缓存之上的缓存,在session factory 范围内有效。
在这篇文章中,我将给出使用ehcache在hibernate配置二级缓存的例子。
这篇文章的结构:
二级缓存是如何工作的
关于ehcache
配置ehcache
配置实体对象
查询缓存
应用例子
源码下载
关于更多二级缓存是如何工作的,可以参考这篇文章。
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>[2.0.0]</version> <type>pom</type> </dependency>
<property key="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</property>
<property key="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>
<class name="com.application.entity.DepartmentEntity" table="..."> <cache usage="read-write"/> </class>
@Entity @Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="department") public class DepartmentEntity implements Serializable { //code }
<property key="hibernate.cache.use_query_cache">true</property>
sessionFactory.getCurrentSession().createQuery("...").setCacheable(true).list();
<property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>
<cache name="com.somecompany.someproject.domain.Country" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" />
<?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> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedemo</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">create</property> <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <mapping class="hibernate.test.dto.DepartmentEntity"></mapping> </session-factory> </hibernate-configuration>
package hibernate.test.dto; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity (name = "dept") @Table(name = "DEPARTMENT", uniqueConstraints = { @UniqueConstraint(columnNames = "ID"), @UniqueConstraint(columnNames = "NAME") }) @Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="department") public class DepartmentEntity implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ID", unique = true, nullable = false) private Integer id; @Column(name = "NAME", unique = true, nullable = false, length = 100) private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package hibernate.test; import java.io.File; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml return new AnnotationConfiguration().configure(new File("hibernate.cgf.xml")).buildSessionFactory(); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } public static void shutdown() { // Close caches and connection pools getSessionFactory().close(); } }
public class TestHibernateEhcache { public static void main(String[] args) { storeData(); try { //Open the hibernate session Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); //fetch the department entity from database first time DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1)); System.out.println(department.getName()); //fetch the department entity again; Fetched from first level cache department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1)); System.out.println(department.getName()); //Let's close the session session.getTransaction().commit(); session.close(); //Try to get department in new session Session anotherSession = HibernateUtil.getSessionFactory().openSession(); anotherSession.beginTransaction(); //Here entity is already in second level cache so no database query will be hit department = (DepartmentEntity) anotherSession.load(DepartmentEntity.class, new Integer(1)); System.out.println(department.getName()); anotherSession.getTransaction().commit(); anotherSession.close(); } finally { System.out.println(HibernateUtil.getSessionFactory().getStatistics().getEntityFetchCount()); //Prints 1 System.out.println(HibernateUtil.getSessionFactory().getStatistics().getSecondLevelCacheHitCount()); //Prints 1 HibernateUtil.shutdown(); } } private static void storeData() { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); DepartmentEntity department = new DepartmentEntity(); department.setName("Human Resource"); session.save(department); session.getTransaction().commit(); } } Output: Hibernate: insert into DEPARTMENT (NAME) values (?) Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=? Human Resource Human Resource Human Resource 1 1