我注意到Wicket的LoadableDetachableModel
(LDM)按设计分离了每个请求(通过RequestCycle.processRequestAndDetach()
)。这可能会在特定情况下导致性能问题,我希望保留缓存数据,同时仍然使用LDM的优势。
假设您有id的实体的详细信息页面。该页面分为选项卡(AjaxTabbedPanel
)。
如果您打开页面,则从DB读取实体以获取给定的ID(进入LDM)。
如果单击第二个选项卡,模型已经分离,将再次重新加载。
在我的情况下,这不是必需的,因为我不想刷新每个请求的数据。
我想在页面上使用LDM,以便页面历史记录可用(只有实体ID将被序列化并按需重新加载数据)。
那么如何修复不必要的重载?
我想出了两个解决方案:
我认为在wicket中已经有了一个解决方案,但我找不到任何解决方案。你知道其他(标准)方法吗?
非常感谢您的回答。
PS:2)的示例实现
private class MyEntityModel extends LoadableDetachableModel<MyEntity> {
private String entityId;
private transient MyEntity modelObject;
public MyEntityModel(String entityId) {
this.entityId = entityId;
}
//call this for explicit reload
public void forceDetach() {
modelObject = null;
detach();
}
@Override
protected MyEntity load() {
if (modelObject != null) {
return modelObject;
}
MyEntity entity = getData(entityId);
modelObject = message;
return message;
}
}
更新: 看来我原来的问题还不够明确。对不起。 目前的行为:
所需行为: Ad 4 - 调用LDM.detach()时,将保留瞬态模型对象 Ad 7 - 如果瞬态模型对象仍在内存中,请使用它。否则加载数据
上面我描述了两种方法,如何实现这种行为。有没有标准或更好的方法?
答案 0 :(得分:2)
有几种方法可以实现您的目标:
我没有使用过1和2,但是2可能是你目前使用的最接近的替代品(并且更快地实现)。 3可能是您实际想要实现的最接近的替代方案,但需要您为应用程序添加一个全新的基础架构 - 取决于您的容器更容易(JavaEE7)或更难(一个普通的旧servlet容器,如Tomcat / Jetty)。 / p>
答案 1 :(得分:1)
我注意到Wicket的LoadableDetachableModel(LDM)在每个请求中都是按设计分离的(通过RequestCycle.processRequestAndDetach())。这可能会在特定情况下导致性能问题,我希望保留缓存数据,同时仍然使用LDM的优势。
您是否知道它实际上会导致性能问题?
听起来您正试图通过构建缓存机制来优化性能。如果实际上你确实遇到了问题并且需要这个问题,那么建立自己的缓存可能是一个更好的解决方案。
如果您正在使用hibernate,您可能希望将hibernate配置为使用Second Level Cache。
如果您不使用休眠,那么 用于持久性的任何机制都可能具有类似的缓存。或者,如果您实际上需要添加自己的,则应该基于现有的缓存机制,例如ehcache。
答案 2 :(得分:0)
大多数人都将使用ORM(JDO或JPA的实现),而最有用的用例是“开放式持久性管理器/会话视图”。相信我,它是最有用的-我已经尝试了很长时间,尝试了所有其他方式来避免出现这种情况,但是它们只是以眼泪和很多多余的错误代码结尾。
“在视图中打开持久性管理器/会话”意味着,当您的应用收到HTTP请求时,它会获得一个新的持久性管理器/会话(具有自己的L1缓存),然后您的代码根据需要使用它来加载对象,通过IModel向Wicket组件提供内容,然后Wicket组件分离在http请求周期中调用其onDetach方法时所拥有的模型引用。在请求结束时,持久性管理器/会话关闭。当然,我们丢失了L1高速缓存,但是它的大多数功能仍然保留在L2高速缓存中。
您有二级缓存吗?
任何好的ORM都将具有2级(L2)缓存,该缓存将缓存持久性管理器在先前的HTTP请求期间加载的所有对象(当然受内存容量限制)。
鉴于这些已经在内存中,因此可以将它们快速复制到为服务新HTTP请求而创建的新持久性管理器的L1缓存中。也就是说,如果对象位于L2缓存中,则ORM不必从数据库中重新加载对象。
运行没有配置L2缓存的ORM的任何人都需要回到ORM学校的第一天,第1.0.1。节。
当加载一个持久对象时,它将“附加”到加载它的持久性管理器。除非先将其与原始持久性管理器分离,然后再将其重新附加到新的持久性管理器,否则不要将其与新的持久性管理器一起使用。
这是Wicket的onDetach为您节省的地方-并且(最后回答了问题;))这就是为什么在每个HTTP请求的末尾都需要进行分离:这是您进行所有ORM分离的地方,并且必须在在每个请求结束时,否则您将在后续的HTTP请求上跨不同的持久性管理器对对象进行交叉授粉-结果总是很糟糕!