Hibernate入门(四)

一 Hibernate缓存

缓存是介于应用程序和数据库之间,对数据库中的数据复制一份到缓存中,其作用就是为了减少应用程序对数据库的访问,访问数据库时先从缓存中取,提高了程序的性能。Hibernate缓存分为一级缓存和二级缓存:

一级缓存:缓存范围是Session中共享,缓存的生命周期依赖于Session的生命周期,Session关闭后,缓存也关闭了,一级缓存是Hibernate内置的,不能卸除。

二级缓存:缓存范围是SessionFactory中共享,使用的是第三方插件,可插拨,缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期。

二 一级缓存

当发生下面操作时,数据放入缓存:

1. save()

2. get()和load()

3. 使用HQL和QBC从数据库查询数据

package com;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

public class Test {

	public static void main(String[] args) {

		SessionFactory factory = new AnnotationConfiguration().configure().buildSessionFactory();
		Session session = factory.openSession();
		Transaction t = session.beginTransaction();

		t.begin();
		User user1 = (User) session.get(User.class,1);
		t.commit();

		t.begin();
		User user2 = (User) session.get(User.class,1);
		t.commit();

		System.out.println("user1==user2:"+(user1==user2));

		session.close();

	}

}

 

结果显示,两个对象是同一个对象。

数据从缓存中清除:

1. evit()将指定的持久化对象从缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象。 
2. clear()将缓存中的所有持久化对象清除,释放其占用的内存资源。

其他缓存操作:

1. contains()判断指定的对象是否存在于缓存中。
2. flush()刷新缓存区的内容,使之与数据库数据保持同步。

三 二级缓存

1.什么是二级缓存?

SessionFactory级别的缓存,可以跨越Session存在,可以被多个Session所共享。

2.适合放到二级缓存中:

(1)经常被访问

(2)改动不大

(3)数量有限

(4)不是很重要的数据,允许出现偶尔并发的数据。

这样的数据非常适合放到二级缓存中的。

用户的权限:用户的数量不大,权限不多,不会经常被改动,经常被访问。

例如组织机构。

思考:什么样的类,里面的对象才适合放到二级缓存中?

改动频繁,类里面对象特别多,BBS好多帖子,这些帖子20000多条,哪些放到缓存中,不能确定。除非你确定有一些经常被访问的,数据量并不大,改动非常少,这样的数据非常适合放到二级缓存中的。

3.二级缓存实现原理:

 Hibernate如何将数据库中的数据放入到二级缓存中?注意,你可以把缓存看做是一个Map对象,它的Key用于存储对象OID,Value用于存储POJO。首先,当我们使用Hibernate从数据库中查询出数据,获取检索的数据后,Hibernate将检索出来的对象的OID放入缓存中key 中,然后将具体的POJO放入value中,等待下一次再次向数据查询数据时,Hibernate根据你提供的OID先检索一级缓存,若有且配置了二级缓存,则检索二级缓存,如果还没有则才向数据库发送SQL语句,然后将查询出来的对象放入缓存中。

不同厂商提供了二级缓存的实现,如EH、OS、Swarm、JBoss等。

四 EH缓存实例

1.准备jar包

2.配置hibernate.cfg.xml

<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">true</property>

3.创建ehcache.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="ehcache.xsd">

<diskStore path="java.io.tmpdir" />

<defaultCache

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

diskPersistent="false"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU" />

</ehcache>

  

4.在需要被缓存的对象的配置文件class标签下添加cache子标签

 <cache usage="read-only"/>

5.测试

package com;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class Test {

	public static void main(String[] args) {

		Configuration cfg = new Configuration();
		cfg.configure("hibernate.cfg.xml");
		SessionFactory factory = cfg.buildSessionFactory();
		Session session = factory.openSession();
		session.beginTransaction();
		User user1 = (User) session.load(User.class,1);
		session.getTransaction().commit();
		session.close();

		Session session1 = factory.openSession();
		session1.beginTransaction();
		User user2 = (User) session1.load(User.class,1);
		session1.getTransaction().commit();
		System.out.println("user1==user2:"+(user1==user2));

		session1.close();

		//factory.close();

	}

}

结果:

不是同一个对象,这个和一级缓存有区别。

其实二级缓存在存储数据的时候,做了一些特殊的处理,当数据从数据库加载到内存的时候,放入一级缓存(之前一级缓存的原理就不细说了),之后数据放入二级缓存了,但是放入二级缓存的数据却不是对象,这一点和一级缓存有区别,一级缓存放入的是一个具体的对象,对象的属性是有值的,所以可以直接获取(并且是同一个对象),当数据放入二级缓存的时候,hibernate内部把该对象装箱了(把具体对象转化成了object对象),但该object对象依然具有和和原始对象一样的属性只不过类型却是object类型(也称散装数据),装箱的同时也把该对象的类型字符串(包名加类型)也保存了一份,具体结构是,把该对象和该对象的类型字符串通过键值对保存了二级缓存(本质是一个map集合所以可以通过键值对保存),但键却很特殊的字符串,键是该类型字符串和该对象的oid(数据主键)的拼接,通过”#”分割,具体是类字符串#oid,对应该对象(object)。当从二级缓存中获取该数据(不能说是对象)的时候,会根据id和类字符去匹配二级缓存的所有key,如果能找到,则通过反射生产一个对象,并返回给用户(程序),这就很合理的解释了为什么不是同一个对象,因为是反射生产的,和很好的解释了为什么要保存该对象的类字符串,那么为什么要反射,而不直接吧该对象拆箱呢?,个人认为:如果拆箱(吧object转化为具体的po对象)就是一个对象,二级缓存是多个线程共享,如果多个用户同时公用同一个对象(内存地址的指向相同),会引发安全问题(反正这样不好)(摘自论坛回答)

参考:http://www.cnblogs.com/200911/archive/2012/10/09/2716873.html

 

时间: 2024-10-21 23:26:17

Hibernate入门(四)的相关文章

Hibernate入门(四)之hibernate中session的创建方式

为什么要专注于session的创建方式 在有些场景必须关注session的创建,比如说在银行转账操作的时候,两个账户转账必须在同一个session中 如上面所示,账户1钱没了,账户2钱却没有到,原因就在于两者不再同一个事务当中,不能实现事务的回滚. getCurrentSession 说明: 1.产生方式的说明 1.先检查当前线程中是否有session 2.如果当前线程中有session,则把session提取出来,直接使用 3.如果当前线程中没有session,则采用openSession方法

第四章 Hibernate入门

第四章 Hibernate入门4.1 框架技术    4.1.1 框架的概念        框架是一个提供了可重用的公共结构的半成品.    4.1.2 主流框架        4.1.2.1 Struts框架        4.1.2.2 Struts2框架        4.1.2.3 Hibernate框架            一个优秀的持久化框架,负责简化对象数据保存到数据库中,或从数据库中读取数据并封装到对象的工作.        4.1.2.4 Spring框架4.2 Hibern

Hibernate入门篇——第一个Hibernate应用

Hibernate入门 第一步: 挑选jar包 在工程下新建lib文件夹,然后将Hibernate基本包复制进去.可以采用Maven来获取这些包: <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.2.7.Final</version> </dependency> 也可

Hibernate 入门教程(总结)

在前面4篇文章,我把Hibernate中的常规配置.单张表操作.一对一单双边配置.一对多.多对一单双边配置.多对多单双边配置及数据库操作都讲了一遍,如果有的地方说错了或者不明白的地方,还请大家指正.我再把几篇文章的地址发一下,方便大家查阅 一.Hibernate入门教程 第一章Hibernate的简单配置.单张表的增删改查操作(student为例) 地址:http://blog.csdn.net/zhangpan19910604/article/details/46654233 二.Hibern

Java使用Protocol Buffers入门四步骤

Protocol Buffers(简称protobuf)是谷歌的一项技术,用于将结构化的数据序列化.反序列化,经常用于网络传输. 这货实际上类似于XML生成和解析,但protobuf的效率高于XML,不过protobuf生成的是字节码,可读性比XML差.类似的还有json.Java的Serializable等. protobuf支持各种语言.本文以Java为例,简单介绍protobuf如何使用.其他语言使用方法类似. 首先需要下载: http://download.csdn.net/downlo

Hibernate入门精讲

学习Hibernate ,我们首先要知道为什么要学习它?它有什么好处?也就是我们为什么要学习框架技术? 还要知道    什么是Hibernate?    为什么要使用Hibernate?    Hibernate的配置文件的作用是什么?          Hibernate映射文件的作用是什么?     Hibernate持久化对象的状态有哪些? 现在我先上面的问题解决了. 一.我们为什么要学习框架技术? 1.框架技术有哪些? 在Java开发中,我们经常使用Struts.Hibernate和Sp

Thinkphp入门 四 —布局、缓存、系统变量 (48)

原文:Thinkphp入门 四 -布局.缓存.系统变量 (48) [控制器操作方法参数设置] http://网址/index.php/控制器/操作方法 [页面跳转] [变量调节器] Smarty变量调节器 TP变量调节器:普通的php函数 (count  strlen   str_replace) 定义:前者的输出,是后者的输入 [子模板包含] 当前模块彼此包含 <include  file=”模板名称”  /> [使用布局layout] 1. 开启布局,配置变量信息config.php 2.

史上最简单的Hibernate入门简单介绍

事实上Hibernate本身是个独立的框架,它不须要不论什么web server或application server的支持.然而,大多数的Hibernate入门介绍都加入了非常多非Hibernate的东西,比方: Tomcat, Eclipse, Log4J,Struts, XDoclet, 甚至JBoss.这easy让人产生Hibernate复杂难懂的误解,特别是打击了刚開始学习的人的积极性. 在这篇文章将不涉及Eclipse, log4j, Struts, Tomcat, XDoclet,

Redbean:入门(四) - 反射机制 以及 事务

<?php //引入rb入口文件 include_once 'rb.php'; //定义dsn以及相关的数据 $dsn = 'mysql:host=localhost;dbname=hwibs_model'; $user = 'root'; $pass = ''; $table = 'link'; //链接数据库 R::setup($dsn,$user,$pass); //链接数据表 $handler = R::dispense($table); //inspect::反射表,将表的字段结构返回