1) 概述:

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

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

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

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

init="false"

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

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

TCHelper.touch();

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

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

2) 代码

/**//*
 * Copyright (c) 2005 Print Information System Co.,Ltd. All Rights Reserved.
 
*/

package com.jxlt.adt.util;

import com.ptf.datastore.QueryManager;
import com.ptf.util.ClassLoaderUtil;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.File;
import java.sql.SQLException;
import java.util.*;

/** *//**
 * 字典表cache
 *
 * 
@author <a href="martin.xus@gmail.com">martin xus
 * 
@version 1.0 ,2005-10-26 11:29:33
 
*/

public class TCHelper {
    
///---------------------------------------------------------------
    /// Instancd Data
    ///---------------------------------------------------------------
    private static final Logger logger = Logger.getLogger(TCHelper.class);

    
private static Map sqlMap = new HashMap();
    
private static Map cache = new HashMap();
    
private static long lastModefied;
    
public static final String CONFIG_FILE = "tc_adt_sql.xml";

    
//---------------------------------------------------------------
    
//  static block
    
//---------------------------------------------------------------
    static {
        logger.info(
"初始化TC Cache..");
        init();
        logger.info(
"初始化TC Cache完成");
    }

    
//---------------------------------------------------------------
    
//  public method
    
//---------------------------------------------------------------

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

    
public static List get(String key) {
        logger.info(
"get tc value with key:" + key);
        
if (StringUtils.isBlank(key))
            
return null;

        
if (reload()) {
            logger.info(
"reloading");
            init();
            logger.info(
"reloaded");
        }

        String _key 
= key.toLowerCase();

        
if (cache.containsKey(_key))
            
return getValue(key);
        
else
            
return emptyList();
    }



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

    
public static List get(String key, List params) {
        logger.info(
"PageHelper.getTCValue: key=" + key + " params=" + params);
        
if (StringUtils.isBlank(key))
            
return emptyList();

        
if (null == params)
            
throw new UnsupportedOperationException("不支持params为空的查询!");

        String _key 
= key.toLowerCase();

        
if (sqlMap.containsKey(_key)) {
            TCModel model 
= (TCModel) sqlMap.get(_key);
            
//logger.info("model:" + model);
            try {
                
//todo:是否cache该变量
//                cache.put(_key, _list);
                return QueryManager.excuteSql(model.getSql(), params);
            }
 catch (SQLException e) {
                
return emptyList();
            }

        }
 else {
            logger.debug(
"invalid key!");
        }

        
return emptyList();
    }


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

    
public static void touch() {
        File file 
= getFile();
        file.setLastModified(System.currentTimeMillis());
    }


    
/** *//**
     * 清除所有的cache,包括 cache 和 sqlMap
     
*/

    
public static void clearAll() {
        cache.clear();
        sqlMap.clear();
    }


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

    
public static void clear(String key) {
        
if (StringUtils.isBlank(key))
            
return;

        String _key 
= key.toLowerCase();

        
if (cache.containsKey(_key))
            cache.remove(_key);
    }

    
//---------------------------------------------------------------
    
//  private method
    
//---------------------------------------------------------------

    
/** *//**
     * 读取xml文件,初始化tc cache
     
*/

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

            
if (model.isInit()) {
                cache.put(key, initTCValues(model));
            }

            sqlMap.put(key, model);
        }

    }


    
/** *//**
     * 
@param file
     * 
@return Element
     
*/

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

    }


    
/** */<