Thinking

快乐编程,开心生活
posts - 21, comments - 27, trackbacks - 0, articles - -5
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

1、查询缓存

  首先需要配置hibernate.cache.use_query_cache=true

如果用ehcache,配置ehcache.xml,注意hibernate3.0以后不是net.sf的包名了

 1 <cache name="net.sf.hibernate.cache.StandardQueryCache"
 2 
 3 maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
 4 
 5 timeToLiveSeconds="7200" overflowToDisk="true"/>
 6 
 7 <cache name="net.sf.hibernate.cache.UpdateTimestampsCache"
 8 
 9 maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
10 
11 

  然后

query.setCacheable(true);//激活查询缓存

query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion,可选

第二行指定要使用的cacheRegion是myCacheRegion,即你可以给每个查询缓存做一个单独的配置,

使用setCacheRegion来做这个指定,需要在ehcache.xml里面配置它:

1 < cache  name ="myCacheRegion"  maxElementsInMemory ="10"  eternal ="false"
2
3 timeToIdleSeconds ="3600"  timeToLiveSeconds ="7200"  overflowToDisk ="true"   />
4
5


如果省略第二行,不设置cacheRegion的话,那么会使用上面提到的标准查询缓存的配置,也就是

net.sf.hibernate.cache.StandardQueryCache

  问题:当hibernate更新数据库的时候,它怎么知道更新哪些查询缓存呢?

    hibernate在一个地方维护每个表的最后更新时间,其实也就是放在上面

net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。

当通过hibernate更新的时候,hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表,当hibernate查询一个缓存是否存在的时候,如果缓存存在,它还要取出缓存的生成时间和这个缓存所查询的表,然后去查找这些表的最后更新时间,如果有一个表在生成时间后更新过了,那么这个缓存是无效的。可以看出,只要更新过一个表,那么凡是涉及到这个表的查询缓存就失效了,因此查询缓存的命中率可能会比较低。

  注意:

    放入缓存中的key是查询的语句,value是查询之后得到的结果集的id列表。

表面看来这样的方案似乎能解决hql利用缓存的问题,但是需要注意的是,构成key的是:

hql生成的sql、sql的参数、排序、分页信息等。也就是说如果你的hql有小小的差异,

比如第一条hql取1-50条数据,第二条hql取20-60条数据,那么hibernate会认为这是两个

完全不同的key,无法重复利用缓存。因此利用率也不高。

   查询缓存必须配合二级缓存一起使用,否则极易出现1+N的情况

   如果不设置"查询缓存",那么hibernate只会缓存使用load()方法获得的单个持久化对象,

如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法

获得的数据结果集的话,就需要设置hibernate.cache.use_query_cache true才行,如果需要"查询缓存",需要在使用Query或Criteria()时设置其setCacheable(true);属性。 
2、Collection缓存

  需要在hbm的collection里面设置

< cache  usage ="read-write" />

假如class是Cat,collection叫children,那么ehcache里面配置

1 < cache  name ="com.xxx.pojo.Cat.children"
2
3 maxElementsInMemory ="20"  eternal ="false"  timeToIdleSeconds ="3600"
4
5 timeToLiveSeconds ="7200"
6
7 overflowToDisk ="true"   />
8

Collection的缓存和前面查询缓存的list一样,也是只保持一串id,但它不会因为这个表更新过就

失效,一个collection缓存仅在这个collection里面的元素有增删时才失效。

这样有一个问题,如果你的collection是根据某个字段排序的,当其中一个元素更新了该字段时,

导致顺序改变时,collection缓存里面的顺序没有做更新 
3、Class缓存(也称二级缓存)

   可由Hibernate提供的二级缓存实现,它存在于SessionFactory级别,

缓存结构可以看作是一个hash table,key是数据库记录的id,value是id对应的pojo对象。

当用户根据id查询对象的时候(load、iterator方法),会首先在缓存中查找,

如果没有找到再发起数据库查询。但是如果使用hql发起查询(find, query方法)

则不会利用二级缓存,而是直接从数据库获得数据,但是它会把得到的数据放到二级缓存备用。也就是说,基于hql的查询,对二级缓存是只写不读的。 
在hibernate.cfg.xml配置:

< property  name ="hibernate.cache.provider_class" >

       org.hibernate.cache.EhCacheProvider

</ property >

hibernate3支持

Hashtable Cache(org.hibernate.cache.HashtableCacheProvider)

EhCache(org.hibernate.cache.EhCacheProvider)

OSCache(org.hibernate.cache.OSCacheProvider)

SwarmCache(org.hibernate.cache.SwarmCacheProvider)

JBossCache(org.hibernate.cache.TreeCacheProvider)

在相应的POJO配置文件中增加:

<!--

指定缓存同步策略:

read-write                           读写型

nonstrict-read-write             非严格读写型

read-only                            只读型

transactional                        事务型

-->

<cache usage="read-write"/> 

Cache read-only nonstrict-read-write read-write transactional
EhCache Yes Yes Yes No
OSCache Yes Yes Yes No
SwarmCache Yes Yes No No
TreeCache Yes No No Yes

     对于一条记录,也就是一个PO来说,是根据ID来找的,缓存的key就是ID,value是POJO。无论

list,load还是iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate

会先取数据库select id出来,然后一个id一个id的load,如果在缓存里面有,就从缓存取,没有

的话就去数据库load。

   当某个ID通过hibernate修改时,hibernate会知道,于是移除缓存。

这样大家可能会想,同样的查询条件,第一次先list,第二次再iterate,就可以使用到缓存了。

实际上这是很难的,因为你无法判断什么时候是第一次,而且每次查询的条件通常是不一样的,假

如数据库里面有100条记录,id从1到100,第一次list的时候出了前50个id,第二次iterate的时候

却查询到30至70号id,那么30-50是从缓存里面取的,51到70是从数据库取的,共发送1+20条sql。

所以我一直认为iterate没有什么用,总是会有1+N的问题。 如果想要对list或者iterate查询的结

果缓存,就要用到查询缓存了。 
  注意:

   对于one-to-many的关联关系,如果对one应用缓存,则应同时对many应用。

   二级缓存的失效机制由hibernate控制,当某条数据被修改之后,hibernate会根据它的id去做

缓存失效操作。基于此机制,如果数据表不是被hibernate独占,那么二级缓存无法得到有效控制

   hibernate 3.0在做批量修改、批量更新的时候,是不会同步更新二级缓存的

   查询缓存和二级缓存是有关联关系的,他们不是完全独立的两套东西。假如一个查询条件hql_1

,第一次被执行的时候,它会从数据库取得数据,然后把查询条件作为key,把返回数据的所有id

列表作为value(请注意仅仅是id)放到查询缓存中,同时整个结果集放到二级缓存,key是id,

value是pojo对象。当你再次执行hql_1,它会从缓存中得到id列表,然后根据这些列表一个一个的

到二级缓存里面去找pojo对象,如果找不到就向数据库发起查询。也就是说,如果二级缓存配置了

超时时间,就有可能出现查询缓存命中了,获得了id列表,但是class里面相应的pojo已经因为超

时被失效,hibernate就会根据id清单,一个一个的去向数据库查询,有多少个id,就执行多少个

sql。该情况将导致性能下降严重。

   查询缓存的失效机制也由hibernate控制,数据进入缓存时会有一个timestamp,它和数据表的

timestamp对应。当hibernate环境内发生save、update等操作时,会更新被操作数据表的

timestamp。用户在获取缓存的时候,一旦命中就会检查它的timestamp是否和数据表的timestamp

匹配,如果不,缓存会被失效。因此查询缓存的失效控制是以数据表为粒度的,只要数据表中任何

一条记录发生一点修改,整个表相关的所有查询缓存就都无效了。因此查询缓存的命中率可能会很

低。 
4、对方法的缓存

  对于调用频率较高的查询类方法,我们希望缓存方法结果

在spring中可利用拦截器(Interceptor)实现,可能如下面的配置:

 1 < beans >
 2
 3      < bean  id ="cacheInterceptor"
 4
 5 class ="org.springframework.aop.interceptor.cache.OSCacheInterceptor" >
 6
 7         <! - 默认刷新时间(秒)- >
 8
 9         < property  name ="defaultRefreshPeriod" >
10
11             < value > 60 </ value >
12
13         </ property >
14
15         < property  name ="identifiers" >
16
17             < props >
18
19                < prop  key ="java.util.Map" > toString </ prop >
20
21             </ props >
22
23         </ property >
24
25      </ bean >
26
27      <! - 正则表达式匹配 - >
28
29      < bean  id ="searcherAdvisor"
30
31 class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
32
33         < property  name ="advice" >
34
35             < ref  local ="cacheInterceptor"   />
36
37         </ property >
38
39         < property  name ="patterns" >
40
41             < list >
42
43                < value > .get. </ value >
44
45             </ list >
46
47         </ property >
48
49      </ bean >
50
51      <! - 自动代理 - >
52
53      < bean  id ="proxyCreator1"
54
55 class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
56
57         < property  name ="beanNames" >
58
59            <!--  需截获方法的bean列表  -->
60
61             < list >
62
63                < value > commonSelect </ value >
64
65             </ list >
66
67         </ property >
68
69         < property  name ="interceptorNames" >
70
71            <!--  截获器列表  -->
72
73             < list >
74
75                < value > searcherAdvisor </ value >
76
77             </ list >
78
79         </ property >
80
81      </ bean >
82
83 < beans >
84
85

 这里通过自动代理创建bean,并指定作用其上的interceptor列表,在commonSelect存在searchAdvisor,

而searchAdvisor对匹配*get*模式的方法调用将通过cacheInterceptor进行处理。

posted @ 2007-02-06 17:31 lixw 阅读(621) | 评论 (0)编辑 收藏

缓存---基础理论篇   
          
1.   缓存
      缓存介于应用程序和永久性数据存储源之间,它的作用是降低应用程序直接读写永久数据存储源的频率,从而提高应用的运行性能。
      缓存中的数据是数据存储源中数据的拷贝,应用程序在运行时直接读写缓存中的数据,只在某些特定时刻按照缓存中的数据来同步更新数据存储源。
      缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。  

2.   各类CACHE简介

2.1.   Java Caching System
       JSC(Java Caching System)是一个用分布式的缓存系统,是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。JCS和其他缓存系统一样,也是一个用于高速读取,低速写入的应用程序。动态内容和报表系统能够获得更好的性能。如果一个网站,有重复的网站结构,使用间歇性更新方式的数据库(而不是连续不断的更新数据库),被重复搜索出相同结果的,就能够通过执行缓存方式改进其性能和伸缩性。  
官方网站 http://jakarta.apache.org/turbine/jcs/

2.2   EHCache
      EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。
官方网站 http://ehcache.sourceforge.net/;

2.3.   OSCache
       OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。
       OSCache有以下特点:
       缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。
       拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。
      永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。
      支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。
      缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
官方网站 http://www.opensymphony.com/oscache/

2.4.   JCache
       JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。
官方网站 http://jcache.sourceforge.net/

 2.5.   ShiftOne
        ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。
官方网站 http://jocache.sourceforge.net/

  2.6.   SwarmCache
        SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。SwarmCache使用JavaGroups来管理从属关系和分布式缓存的通讯。
官方网站 http://swarmcache.sourceforge.net

 2.7.   TreeCache / JBossCache 
        JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。JBossCache包括两个模块:TreeCache和TreeCacheAOP。TreeCache --是一个树形结构复制的事务处理缓存。TreeCacheAOP --是一个"面向对象"缓存,它使用AOP来动态管理POJO(Plain Old Java Objects)
官方网站 http://www.jboss.org/products/jbosscache;

 2.8.   WhirlyCache
        Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。
官方网站 https://whirlycache.dev.java.net/

posted @ 2007-02-06 17:27 lixw 阅读(268) | 评论 (0)编辑 收藏

一、最简单的方式:
设置表单form 的 method=”post” ENCTYPE="multipart/form-data"
通过
InputStream in =servletRequest.getInputStream();
以流的方式处理,它的缺点就不言而喻了

二、commons-fileupload:
官方网站:[http://jakarta.apache.org/commons/fileupload/]
它提供基于Servlet的上传,可上传到内存、文件,且文件的上传位置,最大上传文件字节数可以在程序中设置,
特别是对于多文件上传支持较好,List items = upload.parseRequest(request)就可以处理多文件,其他都不用考虑,
提供了item.isFormField()判断是否为标准表单值的方法,简洁实用,但是可配置仍然不好,对API的依赖性很大

使用步骤:
1、首先判断一个HttpServletRequest是否是一个上传文件的请求:
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
2、处理请求:
2.1、创建基于硬盘存储的工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
/* 或者
DiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);
*/
2.2、设置工厂属性,从而生成个性化ServletFileUpload
//设置最多只允许在内存中存储的数据,单位:字节
factory.setSizeThreshold(yourMaxMemorySize);
// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
factory.setRepository(yourTempDirectory);
2、处理上传文件:
Iterator iter = items.iterator();
while (iter.hasNext()) {
   FileItem item = (FileItem) iter.next();
   //判断是否为标准表单域
   if (item.isFormField()) {
        String name = item.getFieldName();
 String value = item.getString();
   …
     } else {
  String fieldname = item.getFieldName();
  String filename = item.getName();
  String contentType = item.getContentType();
  boolean isInMemory = item.isInMemory();
  long sizeInBytes = item.getSize();
  …
 //直接从内存访问上传数据
 byte[] data = item.get();
   
 //采用流方式读取上传文件
 InputStream stream = item.openStream();

 // 保存到文件
 if (writeToFile) {
 File uploadedFile = new File(storeFilePath);
 item.write(uploadedFile);
    } else {
 //转换为输出流
 InputStream uploadedStream = item.getInputStream();
 ...
 uploadedStream.close();
 }
}
...

三、javazoom的UploadBean:
官方网站:[http://www.javazoom.net/jzservlets/uploadbean/uploadbean.html]

功能强大,支持上传到文件系统,数据库,同时它还有一些高级功能,如对上传的监听,overwrite过滤器、自定义解析器、
overwrite策略、黑名单、白名单等,特别是它采用了JavaBean方式,所以在JSP页面可以轻松的采用

从而实现上传到硬盘目录但是它的源代码是需要Money的,我们只能得到它的jar包和API Doc,
同时它对多文件上传处理的不是很好(我觉得)。

官方网站上有详细的说明供参考。

四、Jspsmartupload
官方网站:[http://www.jspsmart.com/] 可惜一直打不开
这里有一篇文章说明:[http://java.ccidnet.com/art/3737/20060717/638255_1.html]

posted @ 2007-02-06 17:19 lixw 阅读(511) | 评论 (0)编辑 收藏

 1 < script language = " javascript " >  
 2 // 行追加 
 3 function  lineAdd() 
 4
 5 var  count  =   1
 6 var  newLine_1  =   " <tr> "  
 7 newLine_1  +=   " <td><input type='file' size='30' name='uploadfile "   +  count  +   " '></td> "
 8 count ++
 9 newLine_1  +=   " <td><input type='button' value='删除' style='cursor:hand' onClick='lineDel(this)'></td> "
10 newLine_1  +=   " </tr> "
11
12 var  tmp  =   ""
13 tmp  =   " <table id='D1'> "
14 tmp  +=  D1.innerHTML; 
15 tmp  +=  newLine_1; 
16 tmp  +=   " </table> "
17 D1.outerHTML  =  tmp; 
18 }
 
19
20 // 行删除 
21 function  lineDel(btn) 
22
23 D1.deleteRow(btn.parentNode.parentNode.rowIndex); 
24 }
 
25
26 </ script >

posted @ 2007-02-06 17:17 lixw 阅读(424) | 评论 (0)编辑 收藏

 1 import  java.security. * ;     
 2    
 3 public   class  MD5 {     
 4    
 5   public   final   static  String getMD5(String s) {     
 6    char  hexDigits[]  =   {     
 7      ' 0 ' ' 1 ' ' 2 ' ' 3 ' ,     
 8      ' 4 ' ' 5 ' ' 6 ' ' 7 ' ,     
 9      ' 8 ' ' 9 ' ' a ' ' b ' ,     
10      ' c ' ' d ' ' e ' ' f ' }
;     
11    try   {     
12     byte [] strTemp  =  s.getBytes();     
13    MessageDigest mdTemp  =  MessageDigest.getInstance( " MD5 " );     
14    mdTemp.update(strTemp);     
15     byte [] md  =  mdTemp.digest();     
16     int  j  =  md.length;     
17     char  str[]  =   new   char [j  *   2 ];     
18     int  k  =   0 ;     
19     for  ( int  i  =   0 ; i  <  j; i ++ {     
20      byte  byte0  =  md[i];     
21     str[k ++ =  hexDigits[byte0  >>>   4   &   0xf ];     
22     str[k ++ =  hexDigits[byte0  &   0xf ];     
23    }
     
24     return   new  String(str);     
25   }
catch  (Exception e) {     
26     return   null ;     
27   }
     
28  }
     
29      
30   public   static   void  main(String[] args) {     
31    
32   System.out.print(MD5.getMD5( " abcd " ));     
33  }
    
34 }
    
35

posted @ 2007-02-06 17:15 lixw 阅读(144) | 评论 (0)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4