- 浏览: 63896 次
- 性别:
- 来自: 武汉
最新评论
-
武大鹏程加内特:
武大鹏程加内特 写道任雅菲 写道
3Q 呵呵
你QQ多少? ...
第十一章 MyEclipse自动生成映射文件(上) -
武大鹏程加内特:
zzy90718 写道
第九章 Spring配置数据连接池 -
武大鹏程加内特:
任雅菲 写道
3Q 呵呵
第十一章 MyEclipse自动生成映射文件(上) -
武大鹏程加内特:
任雅菲 写道
第十一章 MyEclipse自动生成映射文件(上) -
任雅菲:
第十一章 MyEclipse自动生成映射文件(上)
缓存的使用
我们先来模拟一个缓存的机制
以查询学生为示例:
public class Test {
public static void main(String[] args) throws Exception {
MyClassDao myClassDao = new MyClassDao();
StudentDao studentDao = new StudentDao();
Student student = studentDao.findById("4028810027d8be080127d8be0d790002");
System.out.println(student.getName());
Student student2 = studentDao.findById("4028810027d8be080127d8be0d790002");
System.out.println(student2.getName());
}
}
可以看到控制台输出:
很明显的看到执行了两条SQL语句,感觉有点浪费资源,如果我们把第一次查询的结果保存起来,当第二次查询的时候,先看保存了没有,如果有,直接用,如果没有,则再查询数据库.这样就更好一些.
修改StudentDao层,给Dao类增加一个模拟的缓存集合
public class StudentDao {
public static Map<String, Student> cache = new HashMap<String, Student>();
public void create(Student student) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public void delete(Student student) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.delete(student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public Student findById(Serializable id) throws Exception {
Session session = null;
Transaction transaction = null;
Student student = null;
String key = Student.class.getName() + id;
student = cache.get(key);
if (student != null) {
return student;
}
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
student = (Student) session.get(Student.class, id);
cache.put(key, student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return student;
}
}
再一次执行Test的main方法,可以看到结果如下:
只执行了一次查询,这就是缓存的一个作用,但是缓存机制远远不会这么简单,想一下,如果在两次查询之间,对象更新了怎么办,这就涉及到缓存的更新.我们暂时只需要了解一下缓存的机制与简单的实现.因为这一块已经有现成的包和类直接用,不需要我们再从头开发.
缓存的作用主要是用来提高性能,可以简单的理解成一个Map,使用缓存涉及到三个操作:
把数据放入缓存
从缓存中获取数据
删除缓存中无效数据
一级缓存: Session级共享,此缓存只能在session关闭之前使用.
save, update, saveOrUpdate, get, list, iterate, lock这些方法都会将对象放在一级缓存中, 一级缓存不能控制缓存的数量, 所以要注意大批量操作数据时可能造成内在溢出, 可以用evict, clear方法清除缓存中的内容.后面讲到Hibernate批量增加数据时再演示.
看下面的代码:
public Student findById(Serializable id) throws Exception {
Session session = null;
Transaction transaction = null;
Student student = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
student = (Student) session.get(Student.class, id);
System.out.println(student.getName());
Student student1 = (Student) session.get(Student.class, id);
System.out.println(student1.getName());
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return student;
}
可以看到上面的代码中,只查询了一次数据库,但是缓存的作用域太小,没有太大的作用.
二级缓存: SessionFactory级共享
实现为可插拔,通过修改两个开关来改变.
告诉Hibernate,我现在要使用缓存机制:
<property name="hibernate.cache.use_second_level_cache">true</property>
配置二级缓存的提供者,也就是具体厂商提供的实现类<property name="cache.provider_class">
缓存的配置,可以在Hibernate源码包下查找hibernate.properties这个文件,找到Second-level Cache这一块,可以看到所有的配置项
可以看到缓存的实现有很多种,那么怎么选择呢?
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
这需要看你的jar包中有哪个对应的缓存实现包,我们可以看到我们的Hibernate库下
可以看到有一个ehcache-1.2.3.jar包,那么这个时候,我们可以选择使用org.hibernate.cache.EhCacheProvider这个实现类,
我们可以在我们的Hibernate.cfg.xml中加入下面的配置项.
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
接下来,我们还需要告诉Hibernate哪些类需要缓存,还需要在Hibernate.cfg.xml中加入下面的配置项.
<class-cache usage="read-only" class="chapter1.model.Student"/>
usage="read-only"指缓存的策略,有以下几种策略:
read-only是不允许修改缓存,效率最高,通常用到像新闻的分类啊,省市联动等等一些不会改变的信息.
像经常需要改动的,可以使用read-write策略,此策略是线程同步
nonstrict-read-write策略和上面一样,但是线程不同步.
transactional事务策略,如果产生错误,缓存会回滚,实现非常复杂.
还有一种方式配置告诉Hibernate哪些类需要缓存, 不需要在Hibernate.cfg.xml配置,直接在Student.hbm.xml中配置即可(推荐方法)
<class name="chapter1.model.Student" table="students">
<cache usage="read-only" />
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" />
</property>
<many-to-one name="myClass" class="chapter1.model.MyClass">
<column name="student_id" length="32" />
</many-to-one>
</class>
在id前面加上<cache usage="read-only" />, 这就不需要告诉类名了.再次执行Test类的main方法,可以看到只执行了一条SQL语句
Query的查询缓存
首先打开
<property name="hibernate.cache.use_query_cache">true</property>
修改StudentDao层,添加一个findAll()方法
public List<Student> findAll() throws Exception {
Session session = null;
Transaction transaction = null;
List<Student> students = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
Query query = session.createQuery("from Student");
query.setCacheable(true);
students = query.list();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return students;
}
注意这里有一句query.setCacheable(true);//设置缓存开关,使其起作用
再来执行Test的main方法:
public class Test {
public static void main(String[] args) throws Exception {
MyClassDao myClassDao = new MyClassDao();
StudentDao studentDao = new StudentDao();
List<Student> students1 = studentDao.findAll();
List<Student> students2 = studentDao.findAll();
}
}
可以看到只执行了一句select语句.
查询的击中
执行下面的代码:
List<Student> students1 = studentDao.findAll();
System.out.println("查询所有学生");
for (Student s : students1) {
System.out.println(s.getName());
}
Student student = studentDao.findById("4028810027d8be080127d8be0d790003");
System.out.println(student.getName());
可以看到只执行了一条SQL语句, studentDao.findById("4028810027d8be080127d8be0d790003");这句代码的查询并没有执行.当Hibernate执行完了Query query = session.createQuery("from Student")类似于这种查询以后,会将查询结果存放起来,Hibernate存放的时候会这样存放map.put(“复杂的key值”, 对象的Id),所以当你执行按ID查询时,就会先从缓存中查询,这时就会被命中了.
使用缓存时需要注意的几点地方:
读取次数大于修改次数,即不是经常修改的数据进行缓存
缓存的容量不能大于内存
对数据要有独享的控制权,即只能通过我这里操作数据,不能从其它通道操作数据
可以容忍无效的数据出现
我们先来模拟一个缓存的机制
以查询学生为示例:
public class Test {
public static void main(String[] args) throws Exception {
MyClassDao myClassDao = new MyClassDao();
StudentDao studentDao = new StudentDao();
Student student = studentDao.findById("4028810027d8be080127d8be0d790002");
System.out.println(student.getName());
Student student2 = studentDao.findById("4028810027d8be080127d8be0d790002");
System.out.println(student2.getName());
}
}
可以看到控制台输出:
很明显的看到执行了两条SQL语句,感觉有点浪费资源,如果我们把第一次查询的结果保存起来,当第二次查询的时候,先看保存了没有,如果有,直接用,如果没有,则再查询数据库.这样就更好一些.
修改StudentDao层,给Dao类增加一个模拟的缓存集合
public class StudentDao {
public static Map<String, Student> cache = new HashMap<String, Student>();
public void create(Student student) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public void delete(Student student) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.delete(student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public Student findById(Serializable id) throws Exception {
Session session = null;
Transaction transaction = null;
Student student = null;
String key = Student.class.getName() + id;
student = cache.get(key);
if (student != null) {
return student;
}
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
student = (Student) session.get(Student.class, id);
cache.put(key, student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return student;
}
}
再一次执行Test的main方法,可以看到结果如下:
只执行了一次查询,这就是缓存的一个作用,但是缓存机制远远不会这么简单,想一下,如果在两次查询之间,对象更新了怎么办,这就涉及到缓存的更新.我们暂时只需要了解一下缓存的机制与简单的实现.因为这一块已经有现成的包和类直接用,不需要我们再从头开发.
缓存的作用主要是用来提高性能,可以简单的理解成一个Map,使用缓存涉及到三个操作:
把数据放入缓存
从缓存中获取数据
删除缓存中无效数据
一级缓存: Session级共享,此缓存只能在session关闭之前使用.
save, update, saveOrUpdate, get, list, iterate, lock这些方法都会将对象放在一级缓存中, 一级缓存不能控制缓存的数量, 所以要注意大批量操作数据时可能造成内在溢出, 可以用evict, clear方法清除缓存中的内容.后面讲到Hibernate批量增加数据时再演示.
看下面的代码:
public Student findById(Serializable id) throws Exception {
Session session = null;
Transaction transaction = null;
Student student = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
student = (Student) session.get(Student.class, id);
System.out.println(student.getName());
Student student1 = (Student) session.get(Student.class, id);
System.out.println(student1.getName());
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return student;
}
可以看到上面的代码中,只查询了一次数据库,但是缓存的作用域太小,没有太大的作用.
二级缓存: SessionFactory级共享
实现为可插拔,通过修改两个开关来改变.
告诉Hibernate,我现在要使用缓存机制:
<property name="hibernate.cache.use_second_level_cache">true</property>
配置二级缓存的提供者,也就是具体厂商提供的实现类<property name="cache.provider_class">
缓存的配置,可以在Hibernate源码包下查找hibernate.properties这个文件,找到Second-level Cache这一块,可以看到所有的配置项
可以看到缓存的实现有很多种,那么怎么选择呢?
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
这需要看你的jar包中有哪个对应的缓存实现包,我们可以看到我们的Hibernate库下
可以看到有一个ehcache-1.2.3.jar包,那么这个时候,我们可以选择使用org.hibernate.cache.EhCacheProvider这个实现类,
我们可以在我们的Hibernate.cfg.xml中加入下面的配置项.
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
接下来,我们还需要告诉Hibernate哪些类需要缓存,还需要在Hibernate.cfg.xml中加入下面的配置项.
<class-cache usage="read-only" class="chapter1.model.Student"/>
usage="read-only"指缓存的策略,有以下几种策略:
read-only是不允许修改缓存,效率最高,通常用到像新闻的分类啊,省市联动等等一些不会改变的信息.
像经常需要改动的,可以使用read-write策略,此策略是线程同步
nonstrict-read-write策略和上面一样,但是线程不同步.
transactional事务策略,如果产生错误,缓存会回滚,实现非常复杂.
还有一种方式配置告诉Hibernate哪些类需要缓存, 不需要在Hibernate.cfg.xml配置,直接在Student.hbm.xml中配置即可(推荐方法)
<class name="chapter1.model.Student" table="students">
<cache usage="read-only" />
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" />
</property>
<many-to-one name="myClass" class="chapter1.model.MyClass">
<column name="student_id" length="32" />
</many-to-one>
</class>
在id前面加上<cache usage="read-only" />, 这就不需要告诉类名了.再次执行Test类的main方法,可以看到只执行了一条SQL语句
Query的查询缓存
首先打开
<property name="hibernate.cache.use_query_cache">true</property>
修改StudentDao层,添加一个findAll()方法
public List<Student> findAll() throws Exception {
Session session = null;
Transaction transaction = null;
List<Student> students = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
Query query = session.createQuery("from Student");
query.setCacheable(true);
students = query.list();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return students;
}
注意这里有一句query.setCacheable(true);//设置缓存开关,使其起作用
再来执行Test的main方法:
public class Test {
public static void main(String[] args) throws Exception {
MyClassDao myClassDao = new MyClassDao();
StudentDao studentDao = new StudentDao();
List<Student> students1 = studentDao.findAll();
List<Student> students2 = studentDao.findAll();
}
}
可以看到只执行了一句select语句.
查询的击中
执行下面的代码:
List<Student> students1 = studentDao.findAll();
System.out.println("查询所有学生");
for (Student s : students1) {
System.out.println(s.getName());
}
Student student = studentDao.findById("4028810027d8be080127d8be0d790003");
System.out.println(student.getName());
可以看到只执行了一条SQL语句, studentDao.findById("4028810027d8be080127d8be0d790003");这句代码的查询并没有执行.当Hibernate执行完了Query query = session.createQuery("from Student")类似于这种查询以后,会将查询结果存放起来,Hibernate存放的时候会这样存放map.put(“复杂的key值”, 对象的Id),所以当你执行按ID查询时,就会先从缓存中查询,这时就会被命中了.
使用缓存时需要注意的几点地方:
读取次数大于修改次数,即不是经常修改的数据进行缓存
缓存的容量不能大于内存
对数据要有独享的控制权,即只能通过我这里操作数据,不能从其它通道操作数据
可以容忍无效的数据出现
发表评论
-
第十七章 离线,命名查询
2010-05-03 20:29 825 离线查询 在Hibernate中,查询有两种方式,一种是 ... -
第十六章 批量插入,多类分页查询
2010-05-03 20:26 955批量插入 有时候我们需要做导入的功能,那么这个时候就需要批量插 ... -
第十五章 事务边界问题
2010-05-03 20:24 2590 事务边界问题 我们先回顾一下我们现在写的代码: 可 ... -
第十三章 lazy懒加载
2010-05-03 20:12 944lazy属性:懒加载 作用:当调用方法的时候才去执行要执行的S ... -
第十二章 继承关系的映射
2010-05-03 20:07 855继承模型 在企业中经常会有员工的分类 我们在Java对象模型 ... -
第十一章 MyEclipse自动生成映射文件(下)
2010-04-28 19:57 1250选中必要的选项 选择主键生成的策略: 设置类名与数据库 ... -
第十一章 MyEclipse自动生成映射文件(上)
2010-04-28 19:44 3190 设置数据库连接 转换视图 创建新的数据库连接 设置 ... -
第十章 Inverse的作用
2010-04-28 19:04 740Inverse的作用 我们还是拿上一章的班级与学生的示例来说 ... -
第九章 级联,集合映射
2010-04-28 19:03 762级联开关 1.级联是指两个对象之间的操作联动关系,对一个对象执 ... -
第八章 Hibernate分页
2010-04-28 18:55 655Hibernate分页 -
第七章 多对多
2010-04-28 18:50 637 多对多 什么情况下会出现多对多呢?比如学生选课就会出现多 ... -
第六章 一对一关系
2010-04-28 18:49 743什么时候采用一对一关系映射呢? 比如我们有时在网上注册的时候, ... -
第五章 一对多关系
2010-04-28 18:44 797 一对多的关系 在学生与班级对象模型中,通常多个学生实体对应 ... -
第四章 多对一关系
2010-04-28 18:43 838今天我们讲多表操作, 多对一的关系 何为多对一呢? 示例: 学 ... -
第三章 对象的状态
2010-04-28 18:42 852 current_session_context_class ... -
第二章 Hibernate增删改查参考
2010-04-28 18:39 1659Hibernate中对增删改查的小结 mysql中库表N ... -
第二章 策略及对象增删改查操作
2010-04-28 18:37 1066Generator 主键生成器 incre ... -
第二章 对象关系数据库映射基础
2010-04-28 18:35 898Generator 主键生成器 incre ... -
第一章 Hibernate环境搭建
2010-04-28 18:34 1413如果是WEB工程,我们只需 ...
相关推荐
第14章 配置FLV服务器 第15章 Nginx的访问控制 第16章 提供FTP下载 第17章 Nginx与编码 第18章 网页压缩传输 第19章 控制Nginx如何记录日志 第20章 map模块的使用 第21章 Nginx预防应用层DDoS攻击 第22章 为...
第14章 配置FLV服务器 第15章 Nginx的访问控制 第16章 提供FTP下载 第17章 Nginx与编码 第18章 网页压缩传输 第19章 控制Nginx如何记录日志 第20章 map模块的使用 第21章 Nginx预防应用层DDoS攻击 第22章 为...
第14章 配置FLV服务器 第15章 Nginx的访问控制 第16章 提供FTP下载 第17章 Nginx与编码 第18章 网页压缩传输 第19章 控制Nginx如何记录日志 第20章 map模块的使用 第21章 Nginx预防应用层DDoS攻击 第22章 为...
第十四章 SSL 第十五章 单点登录 第十六章 综合实例 第十七章 OAuth2集成 第十八章 并发登录人数控制 第十九章 动态URL权限控制 第二十章 无状态Web应用集成 第二十一章 授予身份及切换身份 第二十二章 集成验证码 ...
2.Redis:是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API 3.MongoD
第十四章 集成的子框架 第十五章 中间件 第十六章 集成已有数据库和应用 第十七章 解读Django的管理界面 第十八章 国际化 第十九章 安全 第二十章 部署Django 附录A 案例学习 附录B 数据模型定义参考 附录C ...
完整版Java web开发教程PPT课件 Java开发进阶教程 第14章 spring mvc介绍,原理以及搭建(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第15章 spring mvc核心对象拦截器(共26页).pptx 完整版...
第十四章: 会话、用户和注册 阅读 14 第十五章: 缓存机制 阅读 15 第十四章 集成的子框架 django.contrib 阅读 16 第十七章: 中间件 阅读 17 第十八章: 集成已有的数据库和应用 阅读 18 第十九章: 国际化 阅读 ...
本书所讲的是Django:一个可以使Web开发工作...第十四章: 会话、用户和注册 第十五章: 缓存机制 第十六章 集成的子框架 第十七章: 中间件 第十八章: 集成已有的数据库和应用 第十九章: 国际化 第二十章: 安全
RabbitMQ、第十三章:Hbase、第十四章:MongoDB、第十五章:Cassandra、第十六章:设计模式、第十七章:负载均衡、第十八章:数据库、第十九章:一致性算法、第二十章:JAVA算法、第二十一章:数据结构、第二十二章...
Django book 2.0 的中文...第十四章: 会话、用户和注册 第十五章: 缓存机制 第十六章: 集成的子框架 django.contrib 第十七章: 中间件 第十八章: 集成已有的数据库和应用 第十九章: 国际化 第二十章: 安全
第十四章: 会话、用户和注册 第十五章: 缓存机制 第十六章 集成的子框架 django.contrib 第十七章: 中间件 第十八章: 集成已有的数据库和应用 第十九章: 国际化 第二十章: 安全
15. 第十四章:会话、用户和注册 16. 第十五章:缓存机制 17. 第十六章:集成的子框架 django.contrib 18. 第十七章:中间件 19. 第十八章:集成已有的数据库和应用 20. 第十九章:国际化 21. 第二十章:安全 ...
第1章 认识ASP.NET 2 ...第14章 数据源控件访问数据库 第15章 数据绑定控件显示数据 第16章 文件处理 第17章 数据缓存 第18章 ASP.NET 2. 第19章 创建Web服务 第20章 ASP.NET 2. 第21章 用ASP.NET 2
第十四章 集成的子框架 第十五章 中间件 完成度 第十六章 集成已有数据库和应用 第十七章 解读Django的管理界面 第十八章 国际化 第十九章 安全 第二十章 部署Django 附录A 案例学习 附录B 数据模型定义参考 附录C ...
第十四章块设备驱动程序 第十五章页高速缓存 第十六章访问文件 第十七章回收页框 第十八章Ext2和Ext3文件系统 第十九章进程通信 第二十章程序的执行 附录一 系统启动 附录二 模块 参考文献 源代码索引
第十四章块设备驱动程序 第十五章页高速缓存 第十六章访问文件 第十七章回收页框 第十八章Ext2和Ext3文件系统 第十九章进程通信 第二十章程序的执行 附录一 系统启动 附录二 模块 参考文献 源代码索引
第十四章块设备驱动程序 第十五章页高速缓存 第十六章访问文件 第十七章回收页框 第十八章Ext2和Ext3文件系统 第十九章进程通信 第二十章程序的执行 附录一 系统启动 附录二 模块 参考文献 源代码索引
ASP.NET MVC 4 Web编程 目录: 第1章:ASP.NET MVC基础 ...第14章:高级路由 第15章:可复用UI组件 第16章:日志 第17章:自动测试 第18章:自动化生成 第19章:部署 附录A ASP.NET MVC与Web Form集成
《深入理解Linux内核》第三版 中文版 第十四章 块设备驱动程序 第十五章 页调高速缓存 第十六章 访问文件 第十七章 回收页框