一级缓存
hibernate一级缓存
一级缓存很短和session的生命周期一致,一级缓存也叫session级的缓存或事务级缓存
那些方法支持一级缓存:
* get()
* load()
* iterate(查询实体对象)
如何管理一级缓存:
* session.clear(),session.evict()
如何避免一次性大量的实体数据入库导致内存溢出
* 先flush,再clear
如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具
/**
* 在同一个session中发出两次load查询
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
//不会发出sql,因为load使用缓存
student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 在同一个session中发出两次get查询
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
//不会发出sql,因为get使用缓存
student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 在同一个session中发出两次iterate查询实体对象
*/
public void testCache3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.createQuery("from Student s where s.id=1").iterate().next();
System.out.println("student.name=" + student.getName());
//会发出查询id的sql,不会发出查询实体对象的sql,因为iterate使用缓存
student = (Student)session.createQuery("from Student s where s.id=1").iterate().next();
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 在同一个session中发出两次iterate查询实体对象
*/
public void testCache4() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
String name = (String)session.createQuery("select s.name from Student s where s.id=1").iterate().next();
System.out.println("student.name=" + name);
//iterate查询普通属性,一级缓存不会缓存,所以发出sql
//一级缓存是缓存实体对象的
name = (String)session.createQuery("select s.name from Student s where s.id=1").iterate().next();
System.out.println("student.name=" + name);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session中发出load查询
*/
public void testCache5() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//会发出查询语句,session间不能共享一级缓存的数据
//因为它会伴随session的生命周期存在和消亡
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 在同一个session中先save,在发出load查询save过的数据
*/
public void testCache6() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student stu = new Student();
stu.setName("王五");
Serializable id = session.save(stu);
//不会发出sql,因为save是使用缓存的
Student student = (Student)session.load(Student.class, id);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 向数据库中批量加入1000条数据
*/
public void testCache7() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
for (int i=0; i<1000; i++) {
Student student = new Student();
student.setName("s_" + i);
session.save(student);
//每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);
}
}
二级缓存
hibernate二级缓存
二级缓存也称进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享
二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存
二级缓存的配置和使用:
* 将echcache.xml文件拷贝到src下
* 开启二级缓存,修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
* 指定缓存产品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 指定那些实体类使用二级缓存(两种方法)
* 在映射文件中采用<cache>标签
* 在hibernate.cfg.xml文件中,采用<class-cache>标签
二级缓存是缓存实体对象的
了解一级缓存和二级缓存的交互
ehcache.xml
<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>
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_cache</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">bjsxt</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 指定缓存产品提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<mapping resource="com/bjsxt/hibernate/Classes.hbm.xml"/>
<mapping resource="com/bjsxt/hibernate/Student.hbm.xml"/>
<class-cache class="com.bjsxt.hibernate.Student" usage="read-only"/>
</session-factory>
</hibernate-configuration>
/**
* 开启两个session,分别调用load
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,因为开启了二级缓存,session是共享二级缓存的
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session,分别调用get
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,因为开启了二级缓存,session是共享二级缓存的
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session,分别调用load,在使用SessionFactory清除二级缓存
*/
public void testCache3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//管理二级缓存
SessionFactory factory = HibernateUtils.getSessionFactory();
//factory.evict(Student.class);
factory.evict(Student.class, 1);
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//会发出查询sql,因为二级缓存中的数据被清除了
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 一级缓存和二级缓存的交互
*/
public void testCache4() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅向二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//发出sql语句,因为session设置了CacheMode为GET,所以二级缓存中没有数据
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//只向二级缓存写数据,而不从二级缓存读数据
session.setCacheMode(CacheMode.PUT);
//会发出查询sql,因为session将CacheMode设置成了PUT
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
查询缓存
hibernate查询缓存
查询缓存是针对普通属性结果集的缓存
对实体对象的结果集只缓存id
查询缓存的生命周期,当前关联的表发生修改,那么查询缓存生命周期结束
查询缓存的配置和使用:
* 在hibernate.cfg.xml文件中启用查询缓存,如:
<property name="hibernate.cache.use_query_cache">true</property>
* 在程序中必须手动启用查询缓存,如:
query.setCacheable(true);
/**
* 开启查询缓存,关闭二级缓存
*
* 开启一个session,分别调用query.list
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s.name from Student s");
//启用查询查询缓存
query.setCacheable(true);
List names = query.list();
for (Iterator iter=names.iterator();iter.hasNext(); ) {
String name = (String)iter.next();
System.out.println(name);
}
System.out.println("-------------------------------------");
query = session.createQuery("select s.name from Student s");
//启用查询查询缓存
query.setCacheable(true);
//没有发出查询sql,因为启用了查询缓存
names = query.list();
for (Iterator iter=names.iterator();iter.hasNext(); ) {
String name = (String)iter.next();
System.out.println(name);
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启查询缓存,关闭二级缓存
*
* 开启两个session,分别调用query.list
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s.name from Student s");
//启用查询查询缓存
query.setCacheable(true);
List names = query.list();
for (Iterator iter=names.iterator();iter.hasNext(); ) {
String name = (String)iter.next();
System.out.println(name);
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
System.out.println("-------------------------------------");
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s.name from Student s");
//启用查询查询缓存
query.setCacheable(true);
//不会发出查询sql,因为查询缓存的生命周期和session无关
List names = query.list();
for (Iterator iter=names.iterator();iter.hasNext(); ) {
String name = (String)iter.next();
System.out.println(name);
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启查询缓存,关闭二级缓存
*
* 开启两个session,分别调用query.iterate
*/
public void testCache3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s.name from Student s");
//启用查询查询缓存
query.setCacheable(true);
for (Iterator iter=query.iterate();iter.hasNext(); ) {
String name = (String)iter.next();
System.out.println(name);
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
System.out.println("-------------------------------------");
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s.name from Student s");
//启用查询查询缓存
query.setCacheable(true);
//查询缓存只对query.list()起作用,query.iterate不起作用,也就是query.iterate不使用
//查询缓存
for (Iterator iter=query.iterate();iter.hasNext(); ) {
String name = (String)iter.next();
System.out.println(name);
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 关闭查询缓存,关闭二级缓存
*
* 开启两个session,分别调用query.list查询实体对象
*/
public void testCache4() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s from Student s");
//启用查询查询缓存
//query.setCacheable(true);
List students = query.list();
for (Iterator iter=students.iterator();iter.hasNext(); ) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
System.out.println("-------------------------------------");
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s from Student s");
//启用查询查询缓存
//query.setCacheable(true);
//会发出查询sql,因为list默认每次都会发出查询sql
List students = query.list();
for (Iterator iter=students.iterator();iter.hasNext(); ) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启查询缓存,关闭二级缓存
*
* 开启两个session,分别调用query.list查询实体对象
*/
public void testCache5() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s from Student s");
//启用查询查询缓存
query.setCacheable(true);
List students = query.list();
for (Iterator iter=students.iterator();iter.hasNext(); ) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
System.out.println("-------------------------------------");
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s from Student s");
//启用查询查询缓存
query.setCacheable(true);
//会发出n条查询语句,因为开启了查询缓存,关闭了二级缓存,那么查询缓存会缓存实体对象的id
//所以hibernate会根据实体对象的id去查询相应的实体,如果缓存中不存在相应的
//实体那么将发出根据实体id查询的sql语句,否则不会发出sql使用缓存中的数据
List students = query.list();
for (Iterator iter=students.iterator();iter.hasNext(); ) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启查询缓存,开启二级缓存
*
* 开启两个session,分别调用query.list查询实体对象
*/
public void testCache6() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s from Student s");
//启用查询查询缓存
query.setCacheable(true);
List students = query.list();
for (Iterator iter=students.iterator();iter.hasNext(); ) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
System.out.println("-------------------------------------");
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Query query = session.createQuery("select s from Student s");
//启用查询查询缓存
query.setCacheable(true);
//不会发出查询sql,因为开启了二级缓存和查询缓存,查询缓存缓存了实体对象的id列表
//hibernate会根据实体对象的id列表到二级缓存中取得相应的数据
List students = query.list();
for (Iterator iter=students.iterator();iter.hasNext(); ) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}