少年阿宾

那些青春的岁月

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

#

REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性。REST提出设计概念和准则为:

1.网络上的所有事物都可以被抽象为资源(resource)

2.每一个资源都有唯一的资源标识(resource identifier),对资源的操作不会改变这些标识

3.所有的操作都是无状态的

REST简化开发,其架构遵循CRUD原则,该原则告诉我们对于资源(包括网络资源)只需要四种行为:创建,获取,更新和删除就可以完成相关的操作和处理。您可以通过统一资源标识符(Universal Resource Identifier,URI)来识别和定位资源,并且针对这些资源而执行的操作是通过 HTTP 规范定义的。其核心操作只有GET,PUT,POST,DELETE。

由于REST强制所有的操作都必须是stateless的,这就没有上下文的约束,如果做分布式,集群都不需要考虑上下文和会话保持的问题。极大的提高系统的可伸缩性。

对于SOAP Webservice和Restful Webservice的选择问题,首先需要理解就是SOAP偏向于面向活动,有严格的规范和标准,包括安全,事务等各个方面的内容,同时SOAP强调操作方法和操作对象的分离,有WSDL文件规范和XSD文件分别对其定义。而REST强调面向资源,只要我们要操作的对象可以抽象为资源即可以使用REST架构风格。

如果从这个意义上讲,是否使用REST就需要考虑资源本身的抽象和识别是否困难,如果本身就是简单的类似增删改查的业务操作,那么抽象资源就比较容易,而对于复杂的业务活动抽象资源并不是一个简单的事情。比如校验用户等级,转账,事务处理等,这些往往并不容易简单的抽象为资源。

其次如果有严格的规范和标准定义要求,而且前期规范标准需要指导多个业务系统集成和开发的时候,SOAP风格由于有清晰的规范标准定义是明显有优势的。我们可以在开始和实现之前就严格定义相关的接口方法和接口传输数据。

简单数据操作,无事务处理,开发和调用简单这些是使用REST架构风格的优势。而对于较为复杂的面向活动的服务,如果我们还是使用REST,很多时候都是仍然是传统的面向活动的思想通过转换工具再转换得到REST服务,这种使用方式是没有意义的。

正如另外一篇文章里面谈到的,REST核心是url和面向资源,url代替了原来复杂的操作方法。REST允许我们通过url设计系统,就像测试驱动开发使用测试用例设计类接口一样。所有可以被抽象为资源的东西都可以使用RESTful的url,当我们以传统的用SOAP方式实现的一个查询订单服务的时候可以看到,这个服务首先存在输入的查询条件,然后才是输出结果集。那么对于类似场景要使用REST,不可避免的会将传统的SOAP服务拆分为一个HTTP POST操作和一个HTTP GET操作。前面是输入,而后面是输出。

使用REST的关键是如何抽象资源,抽象的越精确,对REST的应用越好。如何进行抽象,面向资源的设计和传统的面向结构和对象设计区别,资源和对象,数据库表之间的差别是另外一个在分析设计时候要考虑的问题。在REST分析设计中如何改变传统的SOAP分析设计思想又是一个重要问题。

下文转载自:http://hi.baidu.com/gaohong230/blog/item/cd3924396bc7332fb9998f52.html

在SOA的基础技术实现方式中WebService占据了很重要的地位,通常我们提到WebService第一想法就是SOAP消息在各种传输协议上交互。近几年REST的思想伴随着SOA逐渐被大家接受,同时各大网站不断开放API提供给开发者,也激起了REST风格WebService的热潮。

SOAP

什么是SOAP,我想不用多说,google一把满眼都是。其实SOAP最早是针对RPC的一种解决方案,简单对象访问协议,很轻量,同时作为应用协议可以基于多种传输协议来传递消息(Http,SMTP等)。但是随着SOAP作为WebService的广泛应用,不断地增加附加的内容,使得现在开发人员觉得SOAP很重,使用门槛很高。在SOAP后续的发展过程中,WS-*一系列协议的制定,增加了SOAP的成熟度,也给SOAP增加了负担。

REST

REST其实并不是什么协议也不是什么标准,而是将Http协议的设计初衷作了诠释,在Http协议被广泛利用的今天,越来越多的是将其作为传输协议,而非原先设计者所考虑的应用协议。SOAP类型的WebService就是最好的例子,SOAP消息完全就是将Http协议作为消息承载,以至于对于Http协议中的各种参数(例如编码,错误码等)都置之不顾。其实,最轻量级的应用协议就是Http协议。Http协议所抽象的get,post,put,delete就好比数据库中最基本的增删改查,而互联网上的各种资源就好比数据库中的记录(可能这么比喻不是很好),对于各种资源的操作最后总是能抽象成为这四种基本操作,在定义了定位资源的规则以后,对于资源的操作通过标准的Http协议就可以实现,开发者也会受益于这种轻量级的协议。

REST的思想归结以下有如下几个关键点:

1.面向资源的接口设计

所有的接口设计都是针对资源来设计的,也就很类似于我们的面向对象和面向过程的设计区别,只不过现在将网络上的操作实体都作为资源来看待,同时URI的设计也是体现了对于资源的定位设计。后面会提到有一些网站的API设计说是REST设计,其实是RPC-REST的混合体,并非是REST的思想。

2.抽象操作为基础的CRUD

这点很简单,Http中的get,put,post,delete分别对应了read,update,create,delete四种操作,如果仅仅是作为对于资源的操作,抽象成为这四种已经足够了,但是对于现在的一些复杂的业务服务接口设计,可能这样的抽象未必能够满足。其实这也在后面的几个网站的API设计中暴露了这样的问题,如果要完全按照REST的思想来设计,那么适用的环境将会有限制,而非放之四海皆准的。

3.Http是应用协议而非传输协议

这点在后面各大网站的API分析中有很明显的体现,其实有些网站已经走到了SOAP的老路上,说是REST的理念设计,其实是作了一套私有的SOAP协议,因此称之为REST风格的自定义SOAP协议。

4.无状态,自包含

这点其实不仅仅是对于REST来说的,作为接口设计都需要能够做到这点,也是作为可扩展和高效性的最基本的保证,就算是使用SOAP的WebService也是一样。

SOAP Webservice和RESTful Webservice的比较

成熟度(总的来说SOAP在成熟度上优于REST)

SOAP虽然发展到现在已经脱离了初衷,但是对于异构环境服务发布和调用,以及厂商的支持都已经达到了较为成熟的情况。不同平台,开发语言之间通过SOAP来交互的web service都能够较好的互通(在部分复杂和特殊的参数和返回对象解析上,协议没有作很细致的规定,导致还是需要作部分修正)

REST国外很多大网站都发布了自己的开发API,很多都提供了SOAP和REST两种Web Service,根据调查部分网站的REST风格的使用情况要高于SOAP。但是由于REST只是一种基于Http协议实现资源操作的思想,因此各个网站的REST实现都自有一套,在后面会讲诉各个大网站的REST API的风格。也正是因为这种各自实现的情况,在性能和可用性上会大大高于SOAP发布的web service,但统一通用方面远远不及SOAP。由于这些大网站的SP往往专注于此网站的API开发,因此通用性要求不高。

由于没有类似于SOAP的权威性协议作为规范,REST实现的各种协议仅仅只能算是私有协议,当然需要遵循REST的思想,但是这样细节方面有太多没有约束的地方。REST日后的发展所走向规范也会直接影响到这部分的设计是否能够有很好的生命力。

效率和易用性(REST更胜一筹)

SOAP协议对于消息体和消息头都有定义,同时消息头的可扩展性为各种互联网的标准提供了扩展的基础,WS-*系列就是较为成功的规范。但是也由于SOAP由于各种需求不断扩充其本身协议的内容,导致在SOAP处理方面的性能有所下降。同时在易用性方面以及学习成本上也有所增加。

REST被人们的重视,其实很大一方面也是因为其高效以及简洁易用的特性。这种高效一方面源于其面向资源接口设计以及操作抽象简化了开发者的不良设计,同时也最大限度的利用了Http最初的应用协议设计理念。同时,在我看来REST还有一个很吸引开发者的就是能够很好的融合当前Web2.0的很多前端技术来提高开发效率。例如很多大型网站开放的REST风格的API都会有多种返回形式,除了传统的xml作为数据承载,还有(JSON,RSS,ATOM)等形式,这对很多网站前端开发人员来说就能够很好的mashup各种资源信息。

安全性:

这点其实可以放入到成熟度中,不过在当前的互联网应用和平台开发设计过程中,安全已经被提到了很高的高度,特别是作为外部接口给第三方调用,安全性可能会高过业务逻辑本身。

SOAP在安全方面是通过使用XML-Security和XML-Signature两个规范组成了WS-Security来实现安全控制的,当前已经得到了各个厂商的支持,.net ,php ,java 都已经对其有了很好的支持(虽然在一些细节上还是有不兼容的问题,但是互通基本上是可以的)。

REST没有任何规范对于安全方面作说明,同时现在开放REST风格API的网站主要分成两种,一种是自定义了安全信息封装在消息中(其实这和SOAP没有什么区别),另外一种就是靠硬件SSL来保障,但是这只能够保证点到点的安全,如果是需要多点传输的话SSL就无能为力了。安全这块其实也是一个很大的问题,今年在BEA峰会上看到有演示采用SAML2实现的网站间SSO,其实是直接采用了XML-Security和XML-Signature,效率看起来也不是很高。未来REST规范化和通用化过程中的安全是否也会采用这两种规范,是未知的,但是加入的越多,REST失去它高效性的优势越多。

应用设计与改造:

我们的系统要么就是已经有了那些需要被发布出去的服务,要么就是刚刚设计好的服务,但是开发人员的传统设计思想让REST的形式被接受还需要一点时间。同时在资源型数据服务接口设计上来说按照REST的思想来设计相对来说要容易一些,而对于一些复杂的服务接口来说,可能强要去按照REST的风格来设计会有些牵强。这一点其实可以看看各大网站的接口就可以知道,很多网站还要传入function的名称作为参数,这就明显已经违背了REST本身的设计思路。而SOAP本身就是面向RPC来设计的,开发人员十分容易接受,所以不存在什么适应的过程。总的来说,其实还是一个老观念,适合的才是最好的

技术没有好坏,只有是不是合适,一种好的技术和思想被误用了,那么就会得到反效果。REST和SOAP各自都有自己的优点,同时如果在一些场景下如果去改造REST,其实就会走向SOAP(例如安全)。

REST对于资源型服务接口来说很合适,同时特别适合对于效率要求很高,但是对于安全要求不高的场景。而SOAP的成熟性可以给需要提供给多开发语言的,对于安全性要求较高的接口设计带来便利。所以我觉得纯粹说什么设计模式将会占据主导地位没有什么意义,关键还是看应用场景。

同时很重要一点就是不要扭曲了REST现在很多网站都跟风去开发REST风格的接口,其实都是在学其形,不知其心,最后弄得不伦不类,性能上不去,安全又保证不了,徒有一个看似象摸象样的皮囊。

posted @ 2012-05-24 14:55 abin 阅读(599) | 评论 (0)编辑 收藏

进程和程序区别和联系表现在以下方面:
1)程序只是一组指令的有序集合,它本身没有任何运行的含义,它只是
 一个静态的实体。而进程则不同,它是程序在某个数据集上的执行。
 进程是一个动态的实体,它有自己的生命周期。它因创建而产生,因
 调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被
 撤消。反映了一个程序在一定的数据集上运行的全部动态过程。
2)进程和程序并不是一一对应的,一个程序执行在不同的数据集上就成
 为不同的进程,可以用进程控制块来唯一地标识每个进程。而这一点
 正是程序无法做到的,由于程序没有和数据产生直接的联系,既使是
 执行不同的数据的程序,他们的指令的集合依然是一样的,所以无法
 唯一地标识出这些运行于不同数据集上的程序。一般来说,一个进程
 肯定有一个与之对应的程序,而且只有一个。而一个程序有可能没有
 与之对应的进程(因为它没有执行),也有可能有多个进程与之对应(运
 行在几个不同的数据集上)。
3)进程还具有并发性和交往性,这也与程序的封闭性不同。
----------------------------------------------------------------------------------------------

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

----------------------------------------------------------------------------------------------

进程和线程的区别 
 
说法一:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

 

说法二:进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 

线程的划分尺度小于进程,使得多线程程序的并发性高。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

 

说法三:多线程共存于应用程序中是现代操作系统中的基本特征和重要标志。用过UNIX操作系统的读者知道进程,在UNIX操作系统中,每个应用程序的执行都在操作系统内核中登记一个进程标志,操作系统根据分配的标志对应用程序的执行进行调度和系统资源分配,但进程和线程有什么区别呢?

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:

线程的划分尺度小于进程,使得多线程程序的并发性搞。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程(Process)是最初定义在Unix等多用户、多任务操作系统环境下用于表示应用程序在内存环境中基本执行单元的概念。以Unix操作系统为例,进程是Unix操作系统环境中的基本成分、是系统资源分配的基本单位。Unix操作系统中完成的几乎所有用户管理和资源分配等工作都是通过操作系统对应用程序进程的控制来实现的。 

C、C++、Java等语言编写的源程序经相应的编译器编译成可执行文件后,提交给计算机处理器运行。这时,处在可执行状态中的应用程序称为进程。从用户角度来看,进程是应用程序的一个执行过程。从操作系统核心角度来看,进程代表的是操作系统分配的内存、CPU时间片等资源的基本单位,是为正在运行的程序提供的运行环境。进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘等存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。多任务环境下应用程序进程的主要特点包括: 

●进程在执行过程中有内存单元的初始入口点,并且进程存活过程中始终拥有独立的内存地址空间; 

●进程的生存期状态包括创建、就绪、运行、阻塞和死亡等类型; 

●从应用程序进程在执行过程中向CPU发出的运行指令形式不同,可以将进程的状态分为用户态和核心态。处于用户态下的进程执行的是应用程序指令、处于核心态下的应用程序进程执行的是操作系统指令。 

在Unix操作系统启动过程中,系统自动创建swapper、init等系统进程,用于管理内存资源以及对用户进程进行调度等。在Unix环境下无论是由操作系统创建的进程还要由应用程序执行创建的进程,均拥有唯一的进程标识(PID)。 

说法四:应用程序在执行过程中存在一个内存空间的初始入口点地址、一个程序执行过程中的代码执行序列以及用于标识进程结束的内存出口点地址,在进程执行过程中的每一时间点均有唯一的处理器指令与内存单元地址相对应。 

Java语言中定义的线程(Thread)同样包括一个内存入口点地址、一个出口点地址以及能够顺序执行的代码序列。但是进程与线程的重要区别在于线程不能够单独执行,它必须运行在处于活动状态的应用程序进程中,因此可以定义线程是程序内部的具有并发性的顺序代码流。 

Unix操作系统和Microsoft Windows操作系统支持多用户、多进程的并发执行,而Java语言支持应用程序进程内部的多个执行线程的并发执行。多线程的意义在于一个应用程序的多个逻辑单元可以并发地执行。但是多线程并不意味着多个用户进程在执行,操作系统也不把每个线程作为独立的进程来分配独立的系统资源。进程可以创建其子进程,子进程与父进程拥有不同的可执行代码和数据内存空间。而在用于代表应用程序的进程中多个线程共享数据内存空间,但保持每个线程拥有独立的执行堆栈和程序执行上下文(Context)。 

基于上述区别,线程也可以称为轻型进程 (Light Weight Process,LWP)。不同线程间允许任务协作和数据交换,使得在计算机系统资源消耗等方面非常廉价。 

线程需要操作系统的支持,不是所有类型的计算机都支持多线程应用程序。Java程序设计语言将线程支持与语言运行环境结合在一起,提供了多任务并发执行的能力。这就好比一个人在处理家务的过程中,将衣服放到洗衣机中自动洗涤后将大米放在电饭锅里,然后开始做菜。等菜做好了,饭熟了同时衣服也洗好了。 

需要注意的是:在应用程序中使用多线程不会增加 CPU 的数据处理能力。只有在多CPU 的计算机或者在网络计算体系结构下,将Java程序划分为多个并发执行线程后,同时启动多个线程运行,使不同的线程运行在基于不同处理器的Java虚拟机中,才能提高应用程序的执行效率。 
posted @ 2012-05-22 15:19 abin 阅读(2312) | 评论 (0)编辑 收藏

百度移动终端研发工程师

1.写一个字符串逆序的程序,时间复杂度和空间复杂度最低,效率越高越好。

2.实质:二叉树的层序遍历,每层的结点用单链表输出。

3.1-N(N最大32000,且未知),内存只有4K,找出其中的重复数

4.编程题,比较复杂,是个系统设计题,与《编程之美》中3.2,电话号码对应英语单词类似。

百度软件开发工程师

1.有101个数,为[1,100]之间的数,其中一个数是重复的,如何寻找这个重复的数,其时间复杂度和空间复杂度是多少?

2.Java中抽象类与接口的区别。

3.进程与线程之间的联系与区别。(多家公司都在问,好好研究一下)

4.谈谈对设计模式的认识与理解,简单介绍一下你所知道的设计模式。(多家公司都问,Android方向面试必考的)

5.线程、多线程相关(必问)

6.Linux常用的命令,shell编程,grep命令的使用。

7.海量数据查找或者排序,有资源限制要求。(常考的)

Sina无线客户端开发工程师

笔试的题目和7月22日实习生的题目差不多。面试主要问了:

1.二叉树的一些基础知识。

2.Java多线程,对stop()方法的认识,如何安全的终止一个线程。

3.设计模式相关的问题

4.谈谈你对面向对象编程中继承的认识

5.排序算法

网易2012校招无线客户端开发

1.面向对象编程中多态的概念,用伪代码展示出来。

2.斐波那契数列编程,效率越高越好(详见《编程之美》2.9)

3.60W长度为32的字符串一次性读入内存中,大约占用多少内存空间?

4.一个X向量n,如何求其内部的最大距离。

5.在浏览器中输入http://www.163.com,从输入到页面在浏览器中显示出来,期间发生了哪些过程,越详细越好。

6.简单介绍一下Android系统中的Activity,Service, Intent, ContentProvider组件。

7.编程解析一段josn格式内容,并在界面上显示出来。

8.英文阅读,考察英语能力。

9.网络应用分析,发挥自己的主观能动性和积累。

搜狗

  搜狗的题目出的很全,所有职位的题目都在一份卷子上,涉及到数据结构、网络、操作系统、算法、软件工程等多方面,根据自己所投递的职位,有针对性的选择要答的题目即可。

金山

  为了保险,做了运维的题目,难度不大,主要是网络和Linux操作系统方面的,稍微准备一下即可。答题的时候自我感觉良好,结果没收到面试通知,被鄙视了,o(╯□╰)o

Android开发工程师

1.Activity的生命周期(最基本的)

2.Android基本框架结构。

3.Android终止一个进程的方法,如何彻底终止一个程序。

4.如何改写程序,改变android手机中返回键的功能(西安TCL研究院技术面试)。


posted @ 2012-05-22 15:05 abin 阅读(542) | 评论 (0)编辑 收藏

一、SQL删除某些字段重复的记录(只保留一条) 
1.查询出来重复的记录数:
select t.* from test2 t inner join(select name,age from test2 s group by name,age having count(*)>1)b
on t.name=b.name and t.age=b.age

select t.name,t.age,count(*) as num1 from test2 t group by name,age having count(*)>1
2.删除重复的记录数(只保留一条):
delete from test2 t where t.id not in (select max(id) from test2 s group by name,age)

二、一个表中有一个id字段,选出重复大于三的字段:
select id,count(name) from test t group by id having count(name)>=3

两个日期间的天数 :
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;
posted @ 2012-05-22 14:42 abin 阅读(395) | 评论 (0)编辑 收藏

**
* 使用hql 语句进行操作

   * @param hql
* @param offset
* @param length
* @return List
*/
public List getListForPage(final String hql, final int offset,
    final int length) {
   List list = getHibernateTemplate().executeFind(new HibernateCallback() {
    public Object doInHibernate(Session session)
      throws HibernateException, SQLException {
     Query query = session.createQuery(hql);
     query.setFirstResult(offset);
     query.setMaxResults(length);
     List list = query.list();
     return list;
    }
   });
   return list;
}/**
* 使用criterion进行操作
* @param arg
* @param criterions
* @param offset
* @param length
* @return List
*/
protected List getListForPage(final Class arg, final Criterion[] criterions,final int offset, final int length) {
   List list = getHibernateTemplate().executeFind(new HibernateCallback() {
    public Object doInHibernate(Session session)
      throws HibernateException, SQLException {
     Criteria criteria = session.createCriteria(arg);
     //循环遍历添加约束条件
     for (int i = 0; i < criterions.length; i++) {
      criteria.add(criterions[i]);
     }
     criteria.setFirstResult(offset);
     criteria.setMaxResults(length);
     return criteria.list();
    }
   });
   return list;
}

你不是说你用HibernateTemplate了,如果你用的是spring的HibernateTemplate,那么就直接用就行了,如果你是自己写的template,
那你也应该会准备一个HibernateCallback类啊,这才是典型的模板加回调啊

算了,把HibernateCallback也给你贴出来

import org.hibernate.HibernateException;
import org.hibernate.Session;

/*************************************
* 为 Hibernate 所提供的一个 回调接口,
* 此接口定义了 统一 Hibernate的业务操作;
* @author kenshin
*
*/
public interface HibernateCallback {

/**************************************
  * 回调接口的回调方法,此方法使用者无需调用,
  * 它由 模板类来进行回调,并传入一个 session参数,
  * 以便让使用者完成相关业务
  * @param ses
  * @return 执行结果
  * @throws HibernateException
  */
Object doInHibernate(Session ses)
       throws HibernateException;

}
posted @ 2012-05-17 16:54 abin 阅读(561) | 评论 (0)编辑 收藏

Cache简介: 缓存(Cache )是计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝,应用程序在运行时直接读写缓存中的数据,只在某些特定时刻按照缓存中的数据来同步更新数据存储源。
缓存的物理介质通常是内存,而永久性数据存储源的物理介质通常是硬盘或磁盘,应用程序读写内在的速度显然比读写硬盘的速度快,如果缓存中存放的数据量非常大,也会用硬盘作为缓存的物理介质。
缓存的实现不仅需要作为物理介质的硬件,同时还需要用于管理缓存的并发访问和过期等策略的软件。因此,缓存是通过软件和硬件共同实现的。
1.1.    持久化层的缓存的范围
缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。
1) 事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的对象形式。
2) 进程范围:缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据,所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据,但是对象分解为松散的算法比对象序列化的算法要求更快。
3) 集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。
对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。
持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到进程范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存,通常它是必需的;进程范围或集群范围的缓存是持久化层的第二级缓存,通常是可选的。
1.2.    持久化层的缓存的并发访问策略
当多个并发的事务同时访问持久化层的缓存的相同数据时,会引起并发问题,必须采用必要的事务隔离措施。
在进程范围或集群范围的缓存,即第二级缓存,会出现并发问题。因此可以设定以下四种类型的并发访问策略,每一种策略对应一种事务隔离级别。
1) 事务型(Transactional)策略:仅仅在受管理环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。
2) 读写型(read-write)策略:提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题。
3) 非严格读写型(nonstrict-read-write)策略:不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而尽量避免脏读。对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。
4) 只读型策略(read-only):对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。
事务型并发访问策略是事务隔离级别最高,只读型的隔离级别最低。事务隔离级别越高,并发性能就越低。
2.    Hibernate中的缓存:
Hibernate中提供了两级Cache,第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存。这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载。
Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。
2.1.    一级缓存和二级缓存的比较:

第一级缓存
第二级缓存
存放数据的形式
相互关联的持久化对象
对象的散装数据
缓存的范围
事务范围,每个事务都有单独的第一级缓存
进程范围或集群范围,缓存被同一个进程或集群范围内的所有事务共享
并发访问策略
由于每个事务都拥有单独的第一级缓存,不会出现并发问题,无需提供并发访问策略
由于多个事务会同时访问第二级缓存中相同数据,因此必须提供适当的并发访问策略,来保证特定的事务隔离级别
数据过期策略
没有提供数据过期策略。处于一级缓存中的对象永远不会过期,除非应用程序显式清空缓存或者清除特定的对象
必须提供数据过期策略,如基于内存的缓存中的对象的最大数目,允许对象处于缓存中的最长时间,以及允许对象处于缓存中的最长空闲时间
物理存储介质
内存
内存和硬盘。对象的散装数据首先存放在基于内在的缓存中,当内存中对象的数目达到数据过期策略中指定上限时,就会把其余的对象写入基于硬盘的缓存中。
缓存的软件实现
在Hibernate的Session的实现中包含了缓存的实现
由第三方提供,Hibernate仅提供了缓存适配器(CacheProvider)。用于把特定的缓存插件集成到Hibernate中。
启用缓存的方式
只要应用程序通过Session接口来执行保存、更新、删除、加载和查询数据库数据的操作,Hibernate就会启用第一级缓存,把数据库中的数据以对象的形式拷贝到缓存中,对于批量更新和批量删除操作,如果不希望启用第一级缓存,可以绕过Hibernate API,直接通过JDBC API来执行指操作。
用户可以在单个类或类的单个集合的粒度上配置第二级缓存。如果类的实例被经常读但很少被修改,就可以考虑使用第二级缓存。只有为某个类或集合配置了第二级缓存,Hibernate在运行时才会把它的实例加入到第二级缓存中。
用户管理缓存的方式
第一级缓存的物理介质为内存,由于内存容量有限,必须通过恰当的检索策略和检索方式来限制加载对象的数目。Session的evit()方法可以显式清空缓存中特定对象,但这种方法不值得推荐。
第二级缓存的物理介质可以是内存和硬盘,因此第二级缓存可以存放大量的数据,数据过期策略的maxElementsInMemory属性值可以控制内存中的对象数目。管理第二级缓存主要包括两个方面:选择需要使用第二级缓存的持久类,设置合适的并发访问策略:选择缓存适配器,设置合适的数据过期策略。
2.2.    一级缓存的管理:
当应用程序调用Session的save()、update()、savaeOrUpdate()、get()或load(),以及调用查询接口的list()、iterate()或filter()方法时,如果在Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。
Session为应用程序提供了两个管理缓存的方法:
evict(Object obj):从缓存中清除参数指定的持久化对象。
clear():清空缓存中所有持久化对象。
2.3.    二级缓存的管理:
2.3.1.      Hibernate的二级缓存策略的一般过程如下:
1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。 
2) 把获得的所有数据对象根据ID放入到第二级缓存中。 
3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。 
4) 删除、更新、增加数据的时候,同时更新缓存。
  Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。
2.3.2.      什么样的数据适合存放到第二级缓存中?
1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。
2.3.3.      不适合存放到第二级缓存的数据?
1 经常被修改的数据
2 财务数据,绝对不允许出现并发
3 与其他应用共享的数据。
2.3.4.      常用的缓存插件
Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:
l EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
l OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
l SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
l JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。
2.3.5.      配置二级缓存的主要步骤:
1)      选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。这是最值得认真考虑的步骤。
2)      选择合适的缓存插件,然后编辑该插件的配置文件。
 
 
1.  首先设置EhCache,建立配置文件ehcache.xml,默认的位置在class-path,可以放到你的src目录下:
<ehcache>
    <diskStore path="c:\\ehcache\"/> 
    <defaultCache 
        maxElementsInMemory="10000" 
        eternal="false" 
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        overflowToDisk="true"   
        />
        
    <!-- 设置Category类的缓存的数据过期策略 -->
    <cache name="org.qiujy.domain.cachedemo.Category"
        maxElementsInMemory="100"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        />
        
     <!-- 设置Category类的products集合的缓存的数据过期策略 -->
     <cache name="org.qiujy.domain.cachedemo.Category.products"
        maxElementsInMemory="500"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />
        
    <cache name="org.qiujy.domain.cachedemo.Product"
        maxElementsInMemory="500"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />    
</ehcache>
配置的元素说明:
元素或属性
描述
<diskStore>
设置缓存数据文件的存放目录
<defaultCache>
设置缓存的默认数据过期策略
<cache>
设定具体的命名缓存的数据过期策略
每个命名缓存代表一个缓存区域,每个缓存区域有各自的数据过期策略。命名缓存机制使得用户能够在每个类以及类的每
  2.  在Hibernate配置文件中设置:

<hibernate-configuration>
<session-factory>……<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><property name="cache.use_second_level_cache">true</property>……</session-factory></hibernate-configuration>        此外,可以把cache.use_second_level_cache设置为false关闭所有的hibernate二级缓存。但此属性对指定<cache>的类缺省为true。
 
   3.  为了使用二级缓存,需要在每一个Hibernate Entity上配置。
@Entity   
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)    
public class Forest { ... }   
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)    
@JoinColumn(name="CUST_ID")    
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)    
public SortedSet getTickets() {    
    return tickets;    
}   
@Cache(    
    CacheConcurrencyStrategy usage();                 (1)    
    String region() default "";                       (2)    
    String include() default "all";                   (3)    
)   
(1) usage: 提供缓存对象的事务隔离机制,可选值有以下几种
(NONE, READ_ONLY, NONSTRICT_READ_WRITE(非严格读写), READ_WRITE, TRANSACTIONAL)
(2) region (optional): 指定缓存的区域,默认是类的全限定名。利用缓存区域,可以更精确的指定每个区域的缓存超前策略。如果指定了缓存区域前缀(在hibernate.cfg.xml中设置cache.region_prefix属性为一个字符串),则所有的缓存区域名前将加上这个前缀。
(3) include (optional): all to include all properties, non-lazy to only include non lazy properties (default all).
如果不是使用annotation的话,则是在Hbm文件中添加cache usage="read-only"



http://blog.163.com/seara520@126/blog/static/7206930420102232340810/
posted @ 2012-05-14 09:24 abin 阅读(1104) | 评论 (0)编辑 收藏

1.EhCache是什么
    EhCache是Hibernate的二级缓存技术之一,可以把查询出来的数据存储在内存或者磁盘,节省下次同样查询语句再次查询数据库,大幅减轻数据库压力;

2.EhCache的使用注意点
    当用Hibernate的方式修改表数据(save,update,delete等等),这时EhCache会自动把缓存中关于此表的所有缓存全部删除掉(这样能达到同步)。但对于数据经常修改的表来说,可能就失去缓存的意义了(不能减轻数据库压力);

3.EhCache使用的场合
    3.1比较少更新表数据
        EhCache一般要使用在比较少执行write操作的表(包括update,insert,delete等)[Hibernate的二级缓存也都是这样];
    3.2对并发要求不是很严格的情况
        两台机子中的缓存是不能实时同步的;

4.在项目做的实现
    4.1在工程的src目录下添加ehcache.xml文件,内容如下:
        <?xml version="1.0" encoding="UTF-8"?>
        <ehcache>    
            <diskStore path="java.io.tmpdir" />
          <defaultCache maxElementsInMemory="5"<!--缓存可以存储的总记录量-->
            eternal="false"<!--缓存是否永远不销毁-->
            overflowToDisk="true"<!--当缓存中的数据达到最大值时,是否把缓存数据写入磁盘-->
            timeToIdleSeconds="15"<!--当缓存闲置时间超过该值,则缓存自动销毁-->
                timeToLiveSeconds="120"<!--缓存创建之后,到达该缓存自动销毁-->
          />
        </ehcache>
    4.2在Hibernate.cfg.xml中的mapping标签上面加以下内容:

        <property name="show_sql">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="hibernate.cache.use_query_cache">true</property>
    4.3在要缓存的bean的hbm.xml文件中的class标签下加入以下内容:
       <cache usage="read-only" /><!--也可读写-->
    4.4创建DAO,内容如下:
        Session s = HibernateSessionFactory.getSession();
        Criteria c = s.createCriteria(Xyz.class);
        c.setCacheable(true);//这句必须要有
        System.out.println("第一次读取");
        List l = c.list();
        System.out.println(l.size());
        HibernateSessionFactory.closeSession();

        s = HibernateSessionFactory.getSession();
        c = s.createCriteria(Xyz.class);
        c.setCacheable(true);//这句必须要有
        System.out.println("第二次读取");
        l = c.list();
        System.out.println(l.size());
        HibernateSessionFactory.closeSession();
   4.5这时你会看到打印出来的信息为(表示第二次并没有去读库):
        第一次读取
        Hibernate: *******
        13
        第二次读取
        13

配置Spring+hibernate使用ehcache作为second-level cache

大量数据流动是web应用性能问题常见的原因,而缓存被广泛的用于优化数据库应用。cache被设计为通过保存从数据库里load的数据来减少应用和数据 库之间的数据流动。数据库访问只有当检索的数据不在cache里可用时才必要。hibernate可以用两种不同的对象缓存:first-level cache 和 second-level cache。first-level cache和Session对象关联,而second-level cache是和Session Factory对象关联。

        缺省地,hibernate已经使用基于每个事务的first-level cache。 Hibernate用first-level cache主要是减少在一个事务内的sql查询数量。例如,如果一个对象在同一个事务内被修改多次,hibernate将只生成一个包括所有修改的 UPDATE SQL语句。为了减少数据流动,second-level cache在Session Factory级的不同事务之间保持load的对象,这些对象对整个应用可用,不只是对当前用户正在运行的查询。这样,每次查询将返回已经load在缓存 里的对象,避免一个或更多潜在的数据库事务。

下载ehcache,hibernate3.2必须要ehcache1.2以上才能支持。可以修改log4j配置文件log4j.logger.net.sf.hibernate.cache=debug查看日志

1.在类路径上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:

         maxElementsInMemory             - 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.
         overflowToDisk                  - Sets whether elements can overflow to disk when the in-memory cache
                                          has reached the maxInMemory limit.

         The following attributes are optional:
         timeToIdleSeconds               - Sets the time to idle for an element before it expires.
                                          i.e. The maximum amount of time between accesses before an element expires
                                          Is only used if the element is not eternal.
                                          Optional attribute. A value of 0 means that an Element can idle for infinity.
                                          The default value is 0.
         timeToLiveSeconds               - Sets the time to live for an element before it expires.
                                          i.e. The maximum time between creation time and when an element expires.
                                          Is only used if the element is not eternal.
                                          Optional attribute. A value of 0 means that and Element can live for infinity.
                                          The default value is 0.
         diskPersistent                  - Whether the disk store persists between restarts of the Virtual Machine.
                                          The default value is false.
         diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
                                          is 120 seconds.
         -->

     <defaultCache
         maxElementsInMemory="10000"
         eternal="false"
         overflowToDisk="true"
         timeToIdleSeconds="120"
         timeToLiveSeconds="120"
         diskPersistent="false"
         diskExpiryThreadIntervalSeconds="120"/>
        
     <!-- See http://ehcache.sourceforge.net/documentation/#mozTocId258426 for how to configure caching for your objects -->
</ehcache>

2.applicationContext-hibernate.xml里Hibernate SessionFactory配置:

     <!-- Hibernate SessionFactory -->
     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         <property name="dataSource" ref="dataSource"/>
         <property name="configLocation"><value>classpath:hibernate.cfg.xml</value></property>
         <!-- The property below is commented out b/c it doesn't work when run via
              Ant in Eclipse.   It works fine for individual JUnit tests and in IDEA ??
         <property name="mappingJarLocations">
             <list><value>file:dist/appfuse-dao.jar</value></list>
         </property>
         -->
         <property name="hibernateProperties">
             <props>
                 <prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop>
                 <!--<prop key="hibernate.show_sql">true</prop>-->
                 <prop key="hibernate.max_fetch_depth">3</prop>
                 <prop key="hibernate.hibernate.use_outer_join">true</prop>
                 <prop key="hibernate.jdbc.batch_size">10</prop>
                 <prop key="hibernate.cache.use_query_cache">true</prop>
                 <prop key="hibernate.cache.use_second_level_cache">true</prop>
                 <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                 <!--
                 <prop key="hibernate.use_sql_comments">false</prop>
                 -->
                 <!-- Create/update the database tables automatically when the JVM starts up
                 <prop key="hibernate.hbm2ddl.auto">update</prop> -->
                 <!-- Turn batching off for better error messages under PostgreSQL
                 <prop key="hibernate.jdbc.batch_size">0</prop> -->
             </props>
         </property>
         <property name="entityInterceptor">
            <ref local="auditLogInterceptor"/>
         </property>
     </bean>
说明:如果不设置“查询缓存”,那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、 list()、Iterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要设置 hibernate.cache.use_query_cache true 才行

3.model类里采用Xdoclet生成*.hbm.xml里的cache xml标签,即<cache usage="read-only"/>

/**
* @hibernate.class table="WF_WORKITEM_HIS"
* @hibernate.cache usage="read-write"
*
*/

4.对于"query cache",需要在程序里编码:

         getHibernateTemplate().setCacheQueries(true);
         return getHibernateTemplate().find(hql);

 

 

使用spring和hibernate配置ehcache和query cache
 
1、applicationContext.xml
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>

这两句加到hibernateProperties中
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
   <ref bean="sessionFactory" />
</property>
<property name="cacheQueries">
   <value>true</value>
</property>
</bean>

添加此bean到applicationcontext.xml中。在各个DAO的bean中,更改如下
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
改为
<property name="hibernateTemplate">
<ref bean="hibernateTemplate" />
</property>

2、ehcache.xml文件放在classes根目录即可

3、pojo与ehcache.xml的配置关系
以com.ce.ceblog.pojos.CeblogJournal为例子
在CeblogJournal.hbm.xml中配置:
<class name="CeblogJournal" table="CEBLOG_JOURNAL" lazy="false">
<cache usage="read-write" region="ehcache.xml中的name的属性值"/>
注意:这一句需要紧跟在class标签下面,其他位置无效。

Ehcache.xml文件主体如下
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1" timeToLiveSeconds="1" overflowToDisk="true" />
<cache name="com.ce.ceblog.pojos.CeblogJournal" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" />
hbm文件查找cache方法名的策 略:如果不指定hbm文件中的region="ehcache.xml中的name的属性值",则使用name名为 com.ce.ceblog.pojos.CeblogJournal的cache,如果不存在与类名匹配的cache名称,则用 defaultCache。
如果CeblogJournal包含set集合,则需要另行指定其cache
例如CeblogJournal包含ceblogReplySet集合,则需要
添加如下配置到ehcache.xml中
<cache name="com.ce.ceblog.pojos.CeblogJournal.ceblogReplySet"
maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300"
timeToLiveSeconds="600" overflowToDisk="true" />

另,针对查询缓存的配置如下:
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true"/>
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToLiveSeconds="120"
overflowToDisk="true"/>

4、选择缓存策略依据:
<cache usage="transactional|read-write|nonstrict-read-write|read-only" />
ehcache不支持transactional,其他三种可以支持。
read- only:无需修改, 那么就可以对其进行只读 缓存,注意,在此策略下,如果直接修改数据库,即使能够看到前台显示效果,但是将对象修改至cache中会报error,cache不会发生作用。另:删 除记录会报错,因为不能在read-only模式的对象从cache中删除。
read-write:需要更新数据,那么使用读/写缓存 比较合适,前提:数据库不可以为serializable transaction isolation level(序列化事务隔离级别)
nonstrict-read-write:只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。

5、调试时候使用log4j的log4j.logger.org.hibernate.cache=debug,更方便看到ehcache的操作过程,主要用于调试过程,实际应用发布时候,请注释掉,以免影响性能。

6、 使用ehcache,打印sql语句是正常的,因为query cache设置为true将会创建两个缓存区域:一个用于保存查询结果集 (org.hibernate.cache.StandardQueryCache); 另一个则用于保存最近查询的一系列表的时间戳(org.hibernate.cache.UpdateTimestampsCache)。请注意:在查询 缓存中,它并不缓存结果集中所包含的实体的确切状态;它只缓存这些实体的标识符属性的值、以及各值类型的结果。需要将打印sql语句与最近的cache内 容相比较,将不同之处修改到cache中,所以查询缓存通常会和二级缓存一起使用。

posted @ 2012-05-13 02:08 abin 阅读(317) | 评论 (0)编辑 收藏

假设类A为持久化对象,对应表为tableA,这里没有考虑A和其他表关联的情况。

在spring下配置使用二级缓存:

<property name="hibernateProperties">
<props>
........
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
</props>
</property>

其中${hibernate.cache.provider_class}为net.sf.ehcache.hibernate.EhCacheProvider,${hibernate.cache.use_query_cache}属性值为true(对经常使用的List查询方式,只有在使用查询缓存时,才会从缓存中通过id去get缓存的值;查询缓存一般缓存查询语句和查询结果的id)

A的持久化映射文件中加上cache元素:usage属性的取值根据自己的情况自己指定相应的值

<cache usage="read-write"/>

配置spring的HibernateTemplate对查询语句和结果缓存(cacheQueries值为true):

<bean id="hibernateTemplate"
        <property name="sessionFactory"><ref bean="sessionFactory"/></property>
    <property name="cacheQueries" value="${hibernate.cache.use_query_cache}"></property>
</bean>
开发的spring dao(集成HibernateDaoSupport)应该配置实用这个hibernateTemplate:

<bean id="myDao" of HibernateDaoSupport">
<property name="hibernateTemplate" ref="hibernateTemplate" />
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

在src下新建ehcache.xml文件,文件内容如下:

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

<!--
        eternal:元素是否永久的;
        MemoryStoreEvictionPolicy:default is LRU
    -->
<defaultCache         maxElementsInMemory="10000"
            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"
            overflowToDisk="true"            diskPersistent="false"           diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"/>

<cache name="cn.hnisi.persistence.mmedia.Dmtjbxx"
               maxElementsInMemory="500"               eternal="false"
               timeToIdleSeconds="2400"      timeToLiveSeconds="3600"
               overflowToDisk="false"/>

<cache name="org.hibernate.cache.StandardQueryCache"
        maxElementsInMemory="50" eternal="false" timeToIdleSeconds="600"
        timeToLiveSeconds="1200" overflowToDisk="false"/>

<cache name="org.hibernate.cache.UpdateTimestampsCache"
        maxElementsInMemory="500" eternal="true" overflowToDisk="false"/>

</ehcache>
然后你可以使用HQL查询对象了,比如"from A where name=?";

跟踪查询的sql日志就可以看出第一次是查询数据库,第二次是从缓存中get(见Hibernate ReadWriteCache类的get方法)

问题:什么样的数据适合存放到第二级缓存中?

1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/selley/archive/2008/03/13/2177479.aspx

posted @ 2012-05-13 02:07 abin 阅读(1927) | 评论 (0)编辑 收藏

package com.abin.lee.sort;

public class QuickSort {
 public static void quick(int[] number) {
  sort(number, 0, number.length - 1);
 }

 private static void sort(int[] number, int left, int right) {
  if (left < right) {
   int i = left;
   int j = right + 1;
   while (true) {
    // 向右找
    while (i + 1 < number.length && number[++i] < number[left]);
    // 向左找
    while (j - 1 > -1 && number[--j] > number[left]);
    if (i >= j)
     break;
    swap(number, i, j);
   }
   swap(number, left, j);
   sort(number, left, j - 1);
   // 對左邊進行遞迴
   sort(number, j + 1, right);
   // 對右邊進行遞迴
  }
 }

 private static void swap(int[] number, int i, int j) {
  int t = number[i];
  number[i] = number[j];
  number[j] = t;
 }
 public static void main(String[] args) {
  int[] num=new int[]{1,8,4,2,7,5,6,3};
  quick(num);
  for(int i=0;i<num.length;i++){
   System.out.println(num[i]);
  }
 }
}

posted @ 2012-04-15 15:57 abin 阅读(670) | 评论 (0)编辑 收藏

在类中寻找指定的方法,同时获取该方法的参数列表,例外和返回值

package com.abin.lee.reflect;

import java.lang.reflect.Method;

public class method1 {
 private int f1(Object p,int x) throws NullPointerException{
  if(p==null)
   throw new NullPointerException();
  return x;
 }
 public static void main(String[] args) {
  try {
   Class cls=Class.forName("com.abin.lee.reflect.method1");
   Method[] method=cls.getDeclaredMethods();
   for(int i=0;i<method.length;i++){
    Method m=method[i];
    System.out.println("name="+m.getName());
    System.out.println("decl class="+m.getDeclaringClass());
    Class pvec[]=m.getParameterTypes();
    for(int j=0;j<pvec.length;j++)
     System.out.println("param#"+j+" "+pvec[j]);
    Class evec[]=m.getExceptionTypes();
    for(int k=0;k<evec.length;k++)
     System.out.println("evec="+evec[k]);
    System.out.println("return type="+m.getReturnType());
   }
   
   
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 

}






获取类的构造函数信息,基本上与获取方法的方式相同

package com.abin.lee.reflect;

import java.lang.reflect.Constructor;

public class constructor1 {
 public constructor1(){}
 public constructor1(int i,double d){}
 public static void main(String[] args) {
  try {
   Class<?> con=constructor1.class;
   Constructor cs[]=con.getConstructors();
   for(int i=0;i<cs.length;i++){
    Constructor ct=cs[i];
    System.out.println("name="+ct.getName());
    System.out.println("decl class="+ct.getDeclaringClass());
    Class pvec[]=ct.getParameterTypes();
    for(int j=0;j<pvec.length;j++){
     System.out.println("param="+pvec[j]);
    }
    Class excp[]=ct.getExceptionTypes();
    for(int j=0;j<excp.length;j++){
     System.out.println("exception="+excp[j]);
    }
    
    
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}







获取类中的各个数据成员对象,包括名称。类型和访问修饰符号:

package com.abin.lee.reflect;

import java.lang.reflect.Field;

public class FieldTest {
 private double d;
 public static final int i=37;
 String s="testing";
 public static void main(String[] args) {
  Class<?> cls=FieldTest.class;
  Field field[]=cls.getDeclaredFields();
  for(int i=0;i<field.length;i++){
   Field fd=field[i];
   System.out.println("name="+fd.getName());
   System.out.println("class="+fd.getDeclaringClass());
   System.out.println("type="+fd.getType());
   int mod=fd.getModifiers();
   System.out.println("modifiers="+java.lang.reflect.Modifier.toString(mod));
   
  }
  
  
  
 }
}


posted @ 2012-04-15 00:25 abin 阅读(737) | 评论 (1)编辑 收藏

仅列出标题
共50页: First 上一页 39 40 41 42 43 44 45 46 47 下一页 Last