`
sunyzc
  • 浏览: 2370 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

hibernate一级缓存

阅读更多

 

一级缓存的生命周期和session的生命周期一致,当前sessioin一旦关闭,一级缓存就消失,session间不能共享一级缓存的数据,因此一级缓存也叫session级的缓存或事务级缓存。一级缓存只存实体对象的 ,它不会缓存一般的对象属性(查询缓存可以),即当获得对象后,就将该对象的缓存起来,如果在同一session中如果再去获取这个对象时,它会先判断缓存中有没有该对象的id,如果有就直接从缓存中取出,反之则去数据库中取,取的同时将该对象的缓存起来,有以下方法可以支持一级缓存:

  • get()
  • save()
  • load()
  • iterate(查询实体对象)

Query和Criteria的list()和uniqueResult()只会缓存,但不会使用缓存(除非结合查询缓存)。一级缓存无法取消,但可以管理,可以使用session.clear()、session.evict()清除或驱逐。

以下对hibernate的一级缓存进行代码测试:

hibernate.cfg.xml配置:

 

<!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.url">
      jdbc:mysql://localhost/hibernate_testcache
    </property>
    <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
    </property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect
    </property>
    <property name="hibernate.show_sql">true</property>
 
    <mapping resource="com/sunyzc/hibernate/testcache/User.hbm.xml" />
  </session-factory>
</hibernate-configuration>
 

 

实体Bean:User.java

 

package com.sunyzc.hibernate.testcache;

public class User {
	private int id;
	private String name;

	// getters、setters

}
 

 

User.hbm.xml

 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="com.sunyzc.hibernate.testcache.User" table="t_user">
    <id name="id">
      <generator class="native" />
    </id>
    <property name="name" column="name" type="java.lang.String" />
  </class>
</hibernate-mapping>
 

创建表的工具:ExportDB.java

 

package com.sunyzc.hibernate.testcache;

import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

public class ExportDB {
	public static void main(String[] args) {
		// 读取hibernate.cfg.xml文件
		Configuration cfg = new Configuration().configure();
		SchemaExport export = new SchemaExport(cfg);
		export.create(true, true);
	}
}
 

HibernateUtils.java

 

package com.sunyzc.hibernate.testcache;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
public class HibernateUtils {
  private static SessionFactory factory;
  static {
    try {
      factory = new Configuration().configure().buildSessionFactory();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
 
  public static Session getSession() {
    return factory.openSession();
  }
 
  public static void closeSession(Session session) {
    if (session != null && session.isOpen()) {
      session.close();
    }
  }
}
 

测试1:在同一个session中发出两次load查询

 

public void testCache1() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		User user = (User) session.load(User.class, 1);
		System.out.println("user.name=" + user.getName());
		//不会发出sql,因为load使用缓存
		user = (User) session.load(User.class, 1);
		System.out.println("user.name=" + user.getName());
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

输出结果:

Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
user.name=user0
user.name=user0

测试2:在同一个session中发出两次get查询

 

public void testCache2() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		User user = (User) session.get(User.class, 1);
		System.out.println("user.name=" + user.getName());
		// 不会发出sql,因为get使用缓存
		user = (User) session.get(User.class, 1);
		System.out.println("user.name=" + user.getName());
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

输出结果:

Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
user.name=user0
user.name=user0

测试3:在同一个session中发出两次iterate查询实体对象

 

public void testCache3() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		String hql = "from User u where u.id=1";
		User user = (User) session.createQuery(hql).iterate().next();
		System.out.println("user.name=" + user.getName());
		// 会发出查询id的sql,不会发出查询实体对象的sql,因为iterate使用缓存
		user = (User) session.createQuery(hql).iterate().next();
		System.out.println("user.name=" + user.getName());
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

输出结果:

Hibernate: select user0_.id as col_0_0_ from t_user user0_ where user0_.id=1
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
user.name=user0
Hibernate: select user0_.id as col_0_0_ from t_user user0_ where user0_.id=1
user.name=user0

测试4:在通一个session中发出两次uniqueResult查询实体对象不会缓存,如果第一次用uniqueResult第二次用iterate查询是会缓存的

 

public void testCache4() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		String hql = "from User u where u.id=1";
		User user = (User) session.createQuery(hql).uniqueResult();
		System.out.println("user.name=" + user.getName());
		user = (User) session.createQuery(hql).uniqueResult();
		System.out.println("user.name=" + user.getName());
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

输出结果:

Hibernate: select user0_.id as id0_, user0_.name as name0_ from t_user user0_ where user0_.id=1
user.name=user0
Hibernate: select user0_.id as id0_, user0_.name as name0_ from t_user user0_ where user0_.id=1
user.name=user0

测试5:在通一个session中发出两次list查询实体对象不会缓存

 

public void testCache4() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		List list = session.createQuery("from User u").list();
		System.out.println("user.name=" + list.get(0).getName());
		list = session.createQuery("from User u").list();
		System.out.println("user.name=" + list.get(0).getName());
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

输出结果:

Hibernate: select user0_.id as id0_, user0_.name as name0_ from t_user user0_
user.name=user0
Hibernate: select user0_.id as id0_, user0_.name as name0_ from t_user user0_
user.name=user0

测试6:在同一个session中发出两次iterate查询普通属性不会缓存

 

public void testCache4() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		String hql = "select u.name from User u where u.id=1";
		String name = (String) session.createQuery(hql).iterate().next();
		System.out.println("user.name=" + name);
		// iterate查询普通属性,一级缓存不会缓存,所以发出sql
		// 一级缓存是缓存实体对象的
		name = (String) session.createQuery(hql).iterate().next();
		System.out.println("user.name=" + name);
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

 

输出结果:

Hibernate: select user0_.name as col_0_0_ from t_user user0_ where user0_.id=1
user.name=user0
Hibernate: select user0_.name as col_0_0_ from t_user user0_ where user0_.id=1
user.name=user0

测试7:开启两个session中发出load查询

 

public void testCache7() {
	Session session1 = null;
	Session session2 = null;
	try {
		session1 = HibernateUtils.getSession();
		session2 = HibernateUtils.getSession();
		session1.beginTransaction();
		session2.beginTransaction();

		User user1 = (User) session1.load(User.class, 1);
		System.out.println("user1.name=" + user1.getName());
		// 会发出查询语句,session间不能共享一级缓存的数据
		// 因为它会伴随session的生命周期存在和消亡
		User user2 = (User) session2.load(User.class, 1);
		System.out.println("user2.name=" + user2.getName());

		session1.getTransaction().commit();
		session2.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session1.getTransaction().rollback();
		session2.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session1);
		HibernateUtils.closeSession(session2);
	}
}

 

输出结果:

Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
user1.name=user0
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
user2.name=user0

测试8:在同一个session中先save,再发出load查询save过的数据

 

public void testCache8() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		User u = new User();
		u.setName("张三");
		Serializable id = session.save(u);
		// 不会发出sql,因为save是使用缓存的
		User user = (User) session.load(User.class, id);
		System.out.println("user.name=" + user.getName());
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

输出结果:

Hibernate: insert into t_user (name) values (?)
user.name=张三

如何避免一次性大量的实体数据入库导致内存溢出?

先flush(),再clear()。若不清理缓存,可发现javaw进程占用内存持续增长,到一定程度会内存溢出的。如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具。

测试9:向数据库中批量加入1000条数据

 

public void testCache9() {
	Session session = null;
	try {
		session = HibernateUtils.getSession();
		session.beginTransaction();
		for (int i = 0; i < 1000; i++) {
			User user = new User();
			user.setName("user" + i);
			session.save(user);
			// 每20条数据就强制session将数据持久化
			// 同时清除缓存,避免大量数据造成内存溢出
			if (i % 20 == 0) {
				session.flush();
				session.clear();
			}
		}
		session.getTransaction().commit();
	} catch (Exception e) {
		e.printStackTrace();
		session.getTransaction().rollback();
	} finally {
		HibernateUtils.closeSession(session);
	}
}
 

转自:http://ppjava.com/?p=1825

1
5
分享到:
评论

相关推荐

    hibernate一级缓存、二级缓存和查询缓存

    **hibernate一级缓存、二级缓存和查询缓存** 在Java的持久化框架Hibernate中,缓存机制是提高应用程序性能的关键要素。缓存能够减少数据库的访问次数,提高数据读取速度,并且在一定程度上降低了系统的负载。本文将...

    Hibernate一级缓存和二级缓存

    标题“Hibernate一级缓存和二级缓存”指的是Hibernate框架中的两种缓存机制,它们是提高数据访问性能的关键要素。一级缓存是Session级别的,而二级缓存是SessionFactory级别的,两者在数据库操作中起到了重要的作用...

    hibernate一级缓存和二级缓存的区别与联系

    它是一个事务范围的缓存,也就是说,每个 Hibernate Session 对应一个一级缓存,仅在当前事务中有效。一级缓存主要存储了 Session 在当前事务中加载和修改的对象实例。当 Session 执行 CRUD 操作时,对象会自动放入...

    Hibernate一级缓存、二级缓存以及查询缓存实例

    本文将深入探讨Hibernate的一级缓存、二级缓存以及查询缓存,通过具体的实例来阐述它们的工作原理和使用方法。 首先,我们从一级缓存开始。一级缓存是Hibernate默认提供的缓存,它是每个Session级别的,也被称为...

    Hibernate 一级缓存和二级缓存的区别

    Hibernate 一级缓存和二级缓存的区别

    Hibernat一级缓存(源码)

    在 Hibernate 中,一级缓存是默认开启的一种缓存机制,对于提高应用程序性能有着重要作用。一级缓存位于 Session 对象中,是每个 Session 的私有缓存,它存储了从数据库中读取的对象实例。 一级缓存的工作原理: 1....

    Hibernatehibernate一级缓存.pdf

    这显示了Hibernate一级缓存如何提高性能,避免重复的数据库访问。 总结起来,Hibernate的一级缓存是一个关键特性,它提高了数据访问的效率并降低了数据库的负载。正确理解和使用一级缓存,以及学会管理缓存,是优化...

    hibernate的一级缓存和二级缓存

    《深入理解Hibernate的一级缓存与二级缓存》 Hibernate作为一款强大的ORM框架,其缓存机制是优化数据库操作性能的关键之一。缓存主要分为一级缓存和二级缓存,它们各自承担着不同的职责,共同提升了数据访问的效率...

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    一级缓存是Hibernate默认提供的缓存,每个SessionFactory实例都有一个一级缓存。当对象被加载到内存中时,它们会被存储在一级缓存中。一级缓存是事务级的,意味着它只存在于当前事务内,一旦事务提交或回滚,一级...

    hibernate一级缓存和二级缓存的区别

    用以介绍hibernate 框架的缓存机制

    java模拟hibernate一级缓存示例分享

    其中,一级缓存是Hibernate的核心特性之一,它是一个session级别的缓存,用于存储当前Session中的持久化对象。在这个示例中,我们将通过纯Java代码来模拟Hibernate的一级缓存机制。 首先,我们来看一下一级缓存的...

    hibernate 一级缓存、 持久化对象状态和转换、 多表映射操作

    hibernate 一级缓存、 持久化对象状态和转换、 多表映射操作

    Hibernate一级缓存和二级缓存【内附二级缓存数据存储结构】

    首先,一级缓存是Hibernate默认提供的缓存,每个Session都有一个独立的一级缓存。当我们在操作数据库时,例如查询或更新记录,这些操作实际上是在与一级缓存交互。一级缓存的作用在于减少对数据库的直接访问,提高...

    Hibernate二级缓存+分页功能

    Hibernate一级缓存是指Session级别的缓存,它是默认开启的,每个Session都会维护一个对象缓存,用来存放该Session加载的实体对象。一级缓存的生命周期与Session相同,当Session关闭时,一级缓存中的数据也会被清除。...

    hibernate二级缓存实例

    一级缓存是Session级别的,每个Session都有自己的一级缓存,用于存储当前Session操作的对象。而二级缓存则是SessionFactory级别的,它跨越了多个Session,是全局共享的,可以被多个并发的Session共同使用。 二级...

    hibernate一级和二级缓存配置与详解

    一级缓存是Hibernate默认提供的缓存,它是Session级别的,每个Hibernate Session都有一个私有的、本地的一级缓存。当我们在Session中对对象进行 CRUD(创建、读取、更新、删除)操作时,这些对象会被自动放入一级...

    Hibernate性能优化:一级缓存

    本文将深入探讨Hibernate性能优化中的一个重要概念——一级缓存,并结合给出的压缩包文件“hibernate_cache_level1”,来详细解析一级缓存的工作原理及其优化策略。 一级缓存是Hibernate内置的一种缓存机制,它存在...

    Hibernate一级缓存和二级缓存详解

    Hibernate一级缓存和二级缓存详解 Hibernate是一种流行的基于Java的持久化框架,它提供了两种缓存机制:一级缓存和二级缓存。了解这两种缓存机制是非常重要的,因为它们可以极大地提高应用程序的性能。 一级缓存 ...

    Hibernate二级缓存

    这与一级缓存(Session级别)不同,一级缓存仅存在于单个Session生命周期内,当Session关闭时,一级缓存中的数据会丢失。二级缓存的存在减少了对数据库的直接访问,从而提高了数据读取速度。 为了启用Hibernate的二...

Global site tag (gtag.js) - Google Analytics