1) 概述:
聽說公司有tc cache,可是沒見著它在那里被應(yīng)用了。而且他平時(shí)同事的編碼中,每次要用到字典表的數(shù)據(jù),總是QueryManager查詢數(shù)據(jù)庫。
昨天花了幾個(gè)小時(shí)寫了個(gè)簡(jiǎn)單的TCHelper,用戶緩存TC表。
一般的情況下,我們字典表是不會(huì)發(fā)生變化的,有必要去cache我的字典表。
我的大體思路如下:
一:通過xml配置文件,配置所有的字典表查詢sql.這樣我們的sql和代碼可以不在相干了。
這其中的sql有兩種可能:
? 1:沒有參數(shù),對(duì)于這種sql,在初始化的時(shí)候就將得到數(shù)據(jù),并且緩存起來。
? 2:帶有參數(shù)的,這類sql我們沒有辦法再初始化的時(shí)間就執(zhí)行,我們?cè)趚ml中添加了一個(gè)簡(jiǎn)單的attribute
init="false" 二 :重新加載功能,這有兩種可能:
? 1:字典表數(shù)據(jù)放生改變
? 2:配置的xml文件放生了變化。
對(duì)于字典表數(shù)據(jù)放生改變的情況,目前這個(gè)東西只是簡(jiǎn)單實(shí)現(xiàn),并沒有去檢測(cè)數(shù)據(jù)庫的數(shù)據(jù),而是需要用戶主動(dòng)的方法
TCHelper.touch();
去修改配置文件最后更新時(shí)間。
我們只檢測(cè)文件是否放生變化,如果放生變化才會(huì)去重新加載數(shù)據(jù)。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?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
????//---------------------------------------------------------------


????/**?*//**
?????*?根據(jù)指定的id返回緩存中的字典表數(shù)據(jù)
?????*?首先檢測(cè)是否需要重新加載,若需要,則先加載
?????*
?????*?@param?key?配置在xml中的id
?????*?@return?key對(duì)應(yīng)的字典表數(shù)據(jù),
?????*?????????若沒有對(duì)應(yīng)的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();
????}



????/**?*//**
?????*?這只針對(duì)于在初始化(init)沒有初始化的字典表
?????*
?????*?@param?key????xml配置文件中對(duì)應(yīng)的id
?????*?@param?params?sql參數(shù)
?????*?@return?key對(duì)應(yīng)的字典表數(shù)據(jù),
?????*?????????若沒有對(duì)應(yīng)的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();
????}


????/**?*//**
?????*?修改文件的最后修改時(shí)間
?????*?這樣當(dāng)用戶在查詢字典表數(shù)據(jù)的時(shí)候,會(huì)重新init加載字典表數(shù)據(jù)
?????*?只有在字典表數(shù)據(jù)發(fā)生修改的時(shí)候才需要調(diào)用該方法。
?????*/

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


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

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


????/**?*//**
?????*?清除指定key
對(duì)應(yīng)的字典表數(shù)據(jù)
?????*
?????*?@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());
????????}
????}


????/**?*//**
?????*?@return?File
?????*/

????private?static?File?getFile()?
{
????????File?file?=?new?File(ClassLoaderUtil.getResource(CONFIG_FILE,?TCHelper.class).getFile());

????????if?(!file.exists())?
{
????????????file?=?new?File(TCHelper.class.getResource(CONFIG_FILE).getFile());
????????????if?(!file.exists())
????????????????throw?new?RuntimeException(CONFIG_FILE?+?"?file?not?exists");
????????}

????????return?file;
????}


????/**?*//**
?????*?@param?model
?????*?@return?List
?????*/

????private?static?List?initTCValues(TCModel?model)?
{

????????try?
{
????????????//logger.info("model:"?+?model);
????????????return?QueryManager.excuteSql(model.getSql());

????????}?catch?(SQLException?e)?
{
????????????logger.error("SQLException:"?+?e.getMessage());
????????????return?null;
????????}
????}


????/**?*//**
?????*?@return?boolean
?????*/

????private?static?boolean?reload()?
{
????????File?file?=?getFile();
????????return?lastModefied?!=?file.lastModified();
????}


????/**?*//**
?????*?@return?List
?????*/

????private?static?List?emptyList()?
{
????????return?new?ArrayList();
????}


????/**?*//**
?????*?@param?key
?????*?@return?List
?????*/

????private?static?List?getValue(String?key)?
{
????????return?(List)?cache.get(key);
????}


????/**?*//**
?????*?字典表配置文件對(duì)應(yīng)的Model
?????*/

????protected?static?class?TCModel?
{
????????private?String?id;
????????private?int?amount;
????????private?boolean?init;
????????private?String?sql;


????????public?String?getId()?
{
????????????return?id;
????????}


????????public?void?setId(String?id)?
{
????????????this.id?=?id;
????????}


????????public?int?getAmount()?
{
????????????return?amount;
????????}


????????public?void?setAmount(int?amount)?
{
????????????this.amount?=?amount;
????????}


????????public?boolean?isInit()?
{
????????????return?init;
????????}


????????public?void?setInit(boolean?init)?
{
????????????this.init?=?init;
????????}


????????public?String?getSql()?
{
????????????return?sql;
????????}


????????public?void?setSql(String?sql)?
{
????????????this.sql?=?sql;
????????}

????????public?String?toString()?
{
????????????return?ToStringBuilder.reflectionToString(this,?ToStringStyle.MULTI_LINE_STYLE);
????????}
????}
} 3)xml
我們的xml配置如下:
<?xml?version="1.0"?encoding="GB2312"?>

<sqlquery>

????<query?id="tc_reg_workmode">
????????<sql><![CDATA[
?????????select?t.workmodecode,?t.workmodename
????????from?TC_Reg_WorkMode?t
????????where?t.choiceflag?=?'1'
????????]]>sql>
????query>
????
????<query?id="tc_pub_taxorgdept"?init="false">
????????<sql><![CDATA[
????????select?t.orgdeptcode,t.orgdeptname?from?tc_pub_taxorgdept?t?where?t.auditflag='1'?and?t.orgdeptcode?like??
????????]]>sql>
????query>????
sqlquery>
end