Hibernate快速入门教程(7)

2018-11-17 21:45

[键入文字]

的隔离级别(serializable transaction isolation level),那么就决不能使用这种缓存策略。

nonstrict-read-write: 如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离, 那么比较适合使用非严格读/写缓存策略。

transactional: Hibernate的事务缓存策略提供了全事务的缓存支持,例如对JBoss TreeCache的支持。这样的

缓存只能用于JTA环境中,你必须指定为其hibernate.transaction.manager_lookup_class属性。

>>步骤四、测试二级缓存:现在仍用前面的类来测试,尽管第一个session关闭了,但是我们在第二个session查

询时,仍不会连库,这也就是二级缓存的作用,通常情况下,hibernate查询时会首先在一级缓存中查询数据,再到二级缓存中查询,如果仍查不到才会连库。

这时请注意,尽管我们在一级缓存中清掉了数据,但是在二级缓存中还存有数据,所以在清掉数据后执行的查询操作也不会引起连库,这就是为什么我们最终只看到一条查询语句的原因。强调,前面说用evict或clear只是清掉一级缓存中的内容。

>>步骤五、感知二级缓存:经过上面的测试我们不能明确感知到二级缓存的作用效果,下面我们配置“统计信息”

属性来进行二级缓存信息的获取。

首先我们在主配置文件中配置以下属性:

Statistics st = HibernateUtil.getSessionFactory().getStatistics(); System.out.println(st);

System.out.println(\ System.out.println(\ System.out.println(\

执行后结果为:

put:1 hit:2 miss:1

在进行代码结果分析前先来说两个概念:

命中(miss):命中是指在二级缓存中查到数据,没有找到就称为miss.

命中率:在查询时有多少次是从缓存中得到。 下面我们看上面的执行结果put=1,说明hibernate放了一次数据到

缓存中,这发生在第一次查询时,当不能在二级缓存中找到(这也是为什么会有一次miss的原因)时,会去连库并把数据放到缓存中去,使put变为1.随后进行的三次查找中:第一次仍是从一级缓存中查找到,后两次查找均在二级缓存中查到,所以命中hit=2。

4.二级缓存中的细节问题:

(1)体会save自动填充缓存,save填充缓存不支持id的native方式生成,所以我们先修改User的实体配置文件让id生成方式为:

后,这样修改后再来测试执行结果会发现执行结果为: put:1 hit:3

miss:0 分析:当我们保存User对象到数据库时也会自动把此数据填充到缓存中,所以第一次put实质是发生在保存数据时。这样也就不难解释为什么hit=3,miss=0了。

(2)除了save外,update、saveOrUpdate、list、iterator、get、load(查询时从二级缓存中取数据的三个方法)、Query、Criteria都会填充二级缓存,且它们支持主键的nativa生成方式。 (3)让Query支持二级缓存:首先是主配置中配置如下属性:

5.分步式缓存:

首先我们用图来模拟分步式缓存:

- 31 - / 42

[键入文字]

数 据 库 带缓存的服务器一 带缓存的服务器二 带缓存的服务器N 说明:在大型的web系统中,通常都会采用多个服务器来进行web服务,比如在上面的实例中,我们在服务器一存

有“数据data”,在服务器二中也存有这个数据,但当我们在服务器N中更改这个数据时,如果我们继续访问在服务器一或二的数据,将不能得到正确的数据,这时采取的方式就是只要有服务器改变这个数据就在这些服务器组成的内网中广播这个信息来更新每个改变的数据。虽然服务器在内网中通讯,但是这种方式也是非常耗资源的,后来提出了“中央缓存”来解决此问题,如下图

数 据 库 读写交互:当更改数据时,会更新到库,并且把对象重新保存到这个缓存中。 中央缓存 带缓存的服务器一 带缓存的服务器二 带缓存的服务器N 原理:当我们去某个服务器查询数据时,这个服务器会去中央缓存查询,同样如果下面的某个服务器修改数据时,

中央缓存也会及时把数据更新到库并重新保存新数据。但是如果数据交互快的话,我们仍不能保证数据这些服务器访问中央缓存时是及时数据。比如在服务器一访问中央缓存修改数据时,其它的几个服务器也能访问修改,这样就不能保证及时获取正确信息。所以使用缓存的条件有如下几点:读取大于写入;数据量不能超过内存容量;对数据要有独立的控制;允许无效的数据存在。

十一、事务

1.事务引发的三层架构MVC讨论:

在前面的程序代码中多次用到了事务:

Transaction tx = s.beginTransaction();

对应的jdbc代码:connection. setAutoCommit(false); .....

.....数据处理 .....

tx.commit();

对应的jdbc代码:connection.commit();

- 32 - / 42

[键入文字]

tx.rollback();

对应的jdbc代码:connection.rollback(); 以上的三处事务相关的代码统称为“事务边界”。其实hibernate的事务本质是依赖jdbc的事务来实现,其实对于事务而言,它是应该由业务逻辑层来实现,但是事务所依赖的对象又出现在Model层,所以想严格按照MVC的原理来实现将相当难(在前面我们所写的代码中事务的处理是不符合mvc模式得),但是利用推出的EJB,SPRING这些框架将能达到此目的,下图展示了三层架构,与原始的MVC相比,多了一个持久层。

VIEW(视图)层 表示显示的对象,会经常变化 由美工,页面设计人员管理 Controller(业务逻辑/控制)层 总控整个web层:最稳定 通常由开发人员完成 持久层:ORM (Hibernate框架) MODEL(数据库)层 表示商业规则,数据对象,相对稳定。通常由开发人员,领域专家,数据库管理员共同开发。

2.模拟session context[OSIV]:

>>步骤一,重写工具类,核心代码如下:

package com.asm.hibernate.utils; public class HibernateUtilOSV {

private static SessionFactory sf;

private static ThreadLocal session = new ThreadLocal(); private HibernateUtilOSV() { }

public static Session getThreadLocalSession() { Session s = (Session) session.get(); if (s == null) {

s = getSession();

- 33 - / 42

[键入文字]

}

session.set(s); }

return s; }

public static void closeSession() {

Session s = (Session) session.get(); if (s != null) { s.close();

session.set(null); } }

static {

Configuration cf = new Configuration(); cf.configure();

sf = cf.buildSessionFactory(); }

public static SessionFactory getSessionFactory() { return sf; }

public static Session getSession() { return sf.openSession(); }

>>步骤二、导入servlet包,使用Filter. 内容如下:

package com.asm.hibernate.osv;

public class OpenSessionViewFilter implements Filter { public void destroy() {

// TODO Auto-generated method stub }

public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { Session s = null;

Transaction tx = null; try {

s = HibernateUtilOSV.getThreadLocalSession(); tx = s.beginTransaction(); arg2.doFilter(arg0, arg1); tx.commit();

} catch (Exception e) { if (tx != null) tx.rollback(); } finally {

HibernateUtilOSV.closeSession(); } }

public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }

- 34 - / 42

[键入文字]

>>步骤三、Userdao:

package com.asm.hibernate.osv; public class UserDao {

static void addUseDao(User user) {

HibernateUtilOSV.getThreadLocalSession().save(user); } }

原理流程分析:当有被Filter监测的请求到达此Filter时,Filter会利用工具类来获得一个Session,并用这个

session打开事务,然后再把请求传给下一个Filter.当所有操作执行完成后再返回到这个Filter,如果没有任何异常便可以提交事务,否则回滚事务。这样便可以有效保证事务的完整性,而且有利于懒加载,因为在整个请求的过程中,Session一直未关闭,所以在filter不断向下传递的过程中可以放心的使用session来完成懒加载,这也是解决懒加载的一种方式。

其实OpenSessionInView主要解决了两个问题: 一是实现事务在逻辑层控制。 二是利于懒加载的实现。

下面再来看看工具类:此工具类主要完成了两个工作:

一是生成一个线程级的Session,即是说在一个线程的事务开启到事务结束,一直用的是同一个Session,这样有利于保证事务的完整性,而工具类主要借助了ThradLocal来生成这个线程级的Session。 二是完成Session的关闭。

3.使用Hibernate自带的SessionContext >>步骤一、在主配置文件中增加如下内容:

>>步骤二、重写工具类:核心代码如下:

package com.asm.hibernate.utils; public class HibernateUtilSelf {

private static SessionFactory sf; private HibernateUtilSelf() { }

public static Session getThreadLocalSession() { Session s = sf.getCurrentSession(); if (s == null) {

s = getSession(); }

return s; }

static {

Configuration cf = new Configuration(); cf.configure();

sf = cf.buildSessionFactory(); }

public static SessionFactory getSessionFactory() { return sf;

- 35 - / 42


Hibernate快速入门教程(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:刑法学实验课教学方法研究

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: