请教banq老师:关于缓存的问题

banq老师:
我用jdon建立一个简单的论坛,用ModelListAction的实现类,显示所有主题(包括主题名与点击次数),每次点击一个主题
该主题的点击次数就增加一,主题的SubjectService(POJOService)实现这个功能,查看数据库,可以看到次数被增加,
但是再一次用ModelListAction显示所有主题时,点击次数没有被增加,请问这是为什么,是不是缓存中的Model(主题)没有被更新
但我在更新时(次数增加),有对Model(主题)的PageIteratorSolver执行clearCache()

还有一个问题就是,在一个Action类的实现类的execute中执行WebAppUtil.getService获取POJOService,
假设有一个SubjectService,它的实现类是SubjectServicePOJOImp
第一次执行WebAppUtil.getService时会构造SubjectServicePOJOImp的实例,
但是第二次执行WebAppUtil.getService时就不会构造SubjectServicePOJOImp,为什么?

在此请banq老师指导,谢谢

多谢你能使用Jdon框架,我会一直提供强有力支持。

1.问题原因是缓存没有更新,一般Model执行clearCache()既可清除,但是如果这个Model被嵌入在其他Model里面,也就是有一个父Model,那么就要清除那个父Model了缓存了。这个次数字段应该是主题Model的一个普通字段,如同name一样。

2.因为POJOService缺省使用了对象池,所以,第一次使用会创建,第二次使用一般会使用上次创建好的对象,这如同数据库连接池一样,可提高性能。

多谢banq老师指导,
如果我的更新方法不是使用POJOService的crud功能的(也就是不使用jdonframework.xml的<updateMethod name="updateSubject" />),
假如是一个update(Model m)方法,在pojoServiceImp,JdbcDAO中有它的实现,基本实现与updateSubject(EventModel em)中的代码一样,在方法最后也有调用cleanCache(),这样做有没有清除该Model的缓存,本人觉得好像没有,还有请教banq老师,如何在JdbcDAO中手工(代码实现)清除Model的缓存,
请banq老师指导,谢谢

哦是这样,
jdbcDao中调用cleanCache一般只能清除查询条件的缓存,不能清除单个Model缓存.

我给你做了一个工具类,用来清除特定的Model 缓存,这个类将被加入Jdon框架下一个版本。你一般是Action中,调用后台update服务之前调用本类的clearModelCache方法:



public class ModelUtil {
private final static String module = ModelUtil.class.getName();

private ModelManager modelManager;

public void clearModelCache(ActionMapping actionMapping, HttpServletRequest request) throws Exception {

if (modelManager == null) {
ServletContext sc = request.getSession().getServletContext();
modelManager = (ModelManager) WebAppUtil.getComponentInstance(ComponentKeys.MODEL_MANAGER, sc);
}
//actionMapping是struts的ActionMapping对象
String formName = FormBeanUtil.getFormName(actionMapping);
ModelHandler modelHandler = modelManager.borrowtHandlerObject(formName);
try {
ModelMapping modelMapping = modelHandler.getModelMapping();

String keyName = modelMapping.getKeyName();
String keyValue = request.getParameter(keyName);

ModelKey modelKey = new ModelKey(keyValue, formName);
modelManager.removeCache(keyValue);

} catch (Exception ex) {
Debug.logError(ex, module);
} finally {
modelManager.returnHandlerObject(modelHandler);
}

}

}

非常感谢,正是由于你的建议和问题促使Jdon框架不断进步。

注意:手工清除缓存不是必要的,因为缓存中对象是有存在周期的,这在Cache.xml中设置的,过一段时间缓存将自动清除那些超过配置时间不用的对象,这样你修改的数据将被从数据库重新加载。如果你等不及这些内在变化,可以手工处理:

注意,这段代码关键是:

ModelKey modelKey = new ModelKey(keyValue, formName);
modelManager.removeCache(keyValue);

你必须得到一个ModelKey对象的key值,而ModelKey的创建依赖两种组合参数:Object dataKey, String formName(ActionForm的名称)

或者:Object dataKey, Class modelClass(你的Model 的Class)

注意前面ModelUtil代码中有一句:
String keyValue = request.getParameter(keyName);

这是从前台获得主键的值,如果你已经自己获得,替代这一句。

如果你能自己输入主键的值,例如主键userId="123456",将123456作为作为输入参数调用下面简单方法:



public void clearModelCache(ActionMapping actionMapping, HttpServletRequest request, String keyValue) throws Exception {
if (modelManager == null) {
ServletContext sc = request.getSession().getServletContext();
modelManager = (ModelManager) WebAppUtil.getComponentInstance(ComponentKeys.MODEL_MANAGER, sc);
}
String formName = FormBeanUtil.getFormName(actionMapping);
ModelKey modelKey = new ModelKey(keyValue, formName);
modelManager.removeCache(keyValue);

}

非常感谢banq老师的指导

modelKey = new ModelKey(keyValue,formName);
modelKey是一个临时变量,后面的语句没有用到,生成它做什么用啊

应该是modelManager.removeCache(modelKey)吧

是我糊涂了,应该是
modelManager.removeCache(keyValue);
根据主键值删除,这样,就不用构造一个modelKey,比较方便直接,前面的方法内容就更加简单,只要从容器获得ModelManager实例,直接调用一句:
modelManager.removeCache(keyValue);
既可

前面的代码更正如下;



public void clearModelCache(HttpServletRequest request, String keyValue) throws Exception {
if (modelManager == null) {
ServletContext sc = request.getSession().getServletContext();
modelManager = (ModelManager) WebAppUtil.getComponentInstance(ComponentKeys.MODEL_MANAGER, sc);
}
modelManager.removeCache(keyValue);
}

更简单两句代码:



ModelManager modelManager = (ModelManager) WebAppUtil.getComponentInstance(ComponentKeys.MODEL_MANAGER, request);
modelManager.removeCache(keyValue);