1) 概述:

听说公司有tc cache,可是没见着它在那里被应用了。而且他平时同事的编码中,每次要用到字典表的数据,总是QueryManager查询数据库。

昨天花了几个小时写了个简单的TCHelper,用户缓存TC表。

一般的情况下,我们字典表是不会发生变化的,有必要去cache我的字典表。

我的大体思路如下:
一:通过xml配置文件,配置所有的字典表查询sql.这样我们的sql和代码可以不在相干了。
这其中的sql有两种可能:
  1:没有参数,对于这种sql,在初始化的时候就将得到数据,并且缓存起来。
  2:带有参数的,这类sql我们没有办法再初始化的时间就执行,我们在xml中添加了一个简单的attribute

None.gif init = " false "

二 :重新加载功能,这有两种可能:
  1:字典表数据放生改变
  2:配置的xml文件放生了变化。

对于字典表数据放生改变的情况,目前这个东西只是简单实现,并没有去检测数据库的数据,而是需要用户主动的方法

None.gif TCHelper.touch();

去修改配置文件最后更新时间。

我们只检测文件是否放生变化,如果放生变化才会去重新加载数据。

2) 代码

ExpandedBlockStart.gif ContractedBlock.gif /**/ /*
InBlock.gif * Copyright (c) 2005 Print Information System Co.,Ltd. All Rights Reserved.
ExpandedBlockEnd.gif 
*/

None.gif
package  com.jxlt.adt.util;
None.gif
None.gif
import  com.ptf.datastore.QueryManager;
None.gif
import  com.ptf.util.ClassLoaderUtil;
None.gif
import  org.apache.commons.lang.builder.ToStringBuilder;
None.gif
import  org.apache.commons.lang.builder.ToStringStyle;
None.gif
import  org.apache.log4j.Logger;
None.gif
import  org.jdom.Document;
None.gif
import  org.jdom.Element;
None.gif
import  org.jdom.JDOMException;
None.gif
import  org.jdom.input.SAXBuilder;
None.gif
None.gif
import  java.io.File;
None.gif
import  java.sql.SQLException;
None.gif
import  java.util. * ;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 字典表cache
InBlock.gif *
InBlock.gif * 
@author <a href="martin.xus@gmail.com">martin xus
InBlock.gif * 
@version 1.0 ,2005-10-26 11:29:33
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
public   class  TCHelper  dot.gif {
InBlock.gif    
///---------------------------------------------------------------
InBlock.gif
    /// Instancd Data
InBlock.gif
    ///---------------------------------------------------------------
InBlock.gif
    private static final Logger logger = Logger.getLogger(TCHelper.class);
InBlock.gif
InBlock.gif    
private static Map sqlMap = new HashMap();
InBlock.gif    
private static Map cache = new HashMap();
InBlock.gif    
private static long lastModefied;
InBlock.gif    
public static final String CONFIG_FILE = "tc_adt_sql.xml";
InBlock.gif
InBlock.gif    
//---------------------------------------------------------------
InBlock.gif    
//  static block
InBlock.gif    
//---------------------------------------------------------------
ExpandedSubBlockStart.gifContractedSubBlock.gif
    static dot.gif{
InBlock.gif        logger.info(
"初始化TC Cachedot.gif..");
InBlock.gif        init();
InBlock.gif        logger.info(
"初始化TC Cache完成");
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//---------------------------------------------------------------
InBlock.gif    
//  public method
InBlock.gif    
//---------------------------------------------------------------
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 根据指定的id返回缓存中的字典表数据
InBlock.gif     * 首先检测是否需要重新加载,若需要,则先加载
InBlock.gif     *
InBlock.gif     * 
@param key 配置在xml中的id
InBlock.gif     * 
@return key对应的字典表数据,
InBlock.gif     *         若没有对应的key,则返回emptyList
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static List get(String key) dot.gif{
InBlock.gif        logger.info(
"get tc value with key:" + key);
InBlock.gif        
if (StringUtils.isBlank(key))
InBlock.gif            
return null;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (reload()) dot.gif{
InBlock.gif            logger.info(
"reloadingdot.gif");
InBlock.gif            init();
InBlock.gif            logger.info(
"reloaded");
ExpandedSubBlockEnd.gif        }

InBlock.gif        String _key 
= key.toLowerCase();
InBlock.gif
InBlock.gif        
if (cache.containsKey(_key))
InBlock.gif            
return getValue(key);
InBlock.gif        
else
InBlock.gif            
return emptyList();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 这只针对于在初始化(init)没有初始化的字典表
InBlock.gif     *
InBlock.gif     * 
@param key    xml配置文件中对应的id
InBlock.gif     * 
@param params sql参数
InBlock.gif     * 
@return key对应的字典表数据,
InBlock.gif     *         若没有对应的key,则返回emptyList
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static List get(String key, List params) dot.gif{
InBlock.gif        logger.info(
"PageHelper.getTCValue: key=" + key + " params=" + params);
InBlock.gif        
if (StringUtils.isBlank(key))
InBlock.gif            
return emptyList();
InBlock.gif
InBlock.gif        
if (null == params)
InBlock.gif            
throw new UnsupportedOperationException("不支持params为空的查询!");
InBlock.gif
InBlock.gif        String _key 
= key.toLowerCase();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (sqlMap.containsKey(_key)) dot.gif{
InBlock.gif            TCModel model 
= (TCModel) sqlMap.get(_key);
InBlock.gif            
//logger.info("model:" + model);
ExpandedSubBlockStart.gifContractedSubBlock.gif
            try dot.gif{
InBlock.gif                
//todo:是否cache该变量
InBlock.gif
//                cache.put(_key, _list);
InBlock.gif
                return QueryManager.excuteSql(model.getSql(), params);
ExpandedSubBlockStart.gifContractedSubBlock.gif            }
 catch (SQLException e) dot.gif{
InBlock.gif                
return emptyList();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockStart.gifContractedSubBlock.gif        }
 else dot.gif{
InBlock.gif            logger.debug(
"invalid key!");
ExpandedSubBlockEnd.gif        }

InBlock.gif        
return emptyList();
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 修改文件的最后修改时间
InBlock.gif     * 这样当用户在查询字典表数据的时候,会重新init加载字典表数据
InBlock.gif     * 只有在字典表数据发生修改的时候才需要调用该方法。
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void touch() dot.gif{
InBlock.gif        File file 
= getFile();
InBlock.gif        file.setLastModified(System.currentTimeMillis());
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 清除所有的cache,包括 cache 和 sqlMap
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void clearAll() dot.gif{
InBlock.gif        cache.clear();
InBlock.gif        sqlMap.clear();
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 清除指定key对应的字典表数据
InBlock.gif     *
InBlock.gif     * 
@param key 配置在xml文件中的id名称
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void clear(String key) dot.gif{
InBlock.gif        
if (StringUtils.isBlank(key))
InBlock.gif            
return;
InBlock.gif
InBlock.gif        String _key 
= key.toLowerCase();
InBlock.gif
InBlock.gif        
if (cache.containsKey(_key))
InBlock.gif            cache.remove(_key);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//---------------------------------------------------------------
InBlock.gif    
//  private method
InBlock.gif    
//---------------------------------------------------------------
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 读取xml文件,初始化tc cache
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
private static void init() dot.gif{
InBlock.gif        logger.info(
"TCHelper.init() begin");
InBlock.gif        logger.info(
"Reading config from " + CONFIG_FILE);
InBlock.gif        File file 
= getFile();
InBlock.gif        lastModefied 
= file.lastModified();
InBlock.gif        logger.debug(
"file loaded.");
InBlock.gif        Element element 
= getRootElement(file);
InBlock.gif        Iterator iterator 
= element.getChildren().iterator();
ExpandedSubBlockStart.gifContractedSubBlock.gif        
while (iterator.hasNext()) dot.gif{
InBlock.gif            TCModel model 
= new TCModel();
InBlock.gif            Element e 
= (Element) iterator.next();
InBlock.gif            String id 
= e.getAttributeValue("id");
InBlock.gif            
if (StringUtils.isBlank(id))
InBlock.gif                
continue;
InBlock.gif            String key 
= id.toLowerCase();
InBlock.gif            
//
InBlock.gif
            model.setId(key);
InBlock.gif            model.setAmount(e.getAttributeValue(
"amount"== null ? 2 : Integer.parseInt(e.getAttributeValue("amount")));
InBlock.gif            model.setInit(e.getAttributeValue(
"init"== null || Boolean.getBoolean(e.getAttributeValue("init")));
InBlock.gif            model.setSql(((Element) e.getChildren().get(
0)) .getText());
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (model.isInit()) dot.gif{
InBlock.gif                cache.put(key, initTCValues(model));
ExpandedSubBlockEnd.gif            }

InBlock.gif            sqlMap.put(key, model);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 
@param file
InBlock.gif     * 
@return Element
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
private static Element getRootElement(File file) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
try dot.gif{
InBlock.gif            SAXBuilder saxbuilder 
= new SAXBuilder();
InBlock.gif            Document document 
= saxbuilder.build(file);
InBlock.gif            lastModefied 
= file.lastModified();
InBlock.gif            
return document.getRootElement();
ExpandedSubBlockStart.gifContractedSubBlock.gif        }
 catch (JDOMException e) dot.gif{
InBlock.gif            
throw new RuntimeException("JDOMException:" + e.getMessage());
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */<