JSP临时存储重复数据库结果

时间:2013-05-16 21:12:13

标签: java database jsp

我在JSP中有以下代码,每次用户访问该页面时都会重复运行。所有访问者的数据库结果值都相同。此页面采用参数" service"并且基于它执行SQL查询。第二个SQL查询基于" id"执行。由第一个查询生成。如果有20个不同的服务,它会运行以下查询20次,然后只显示该页面。那么,有什么方法可以暂时存储这些结果(使用缓存或其他东西),这样这些查询只运行一次/第一次访问,然后对其他请求数据库请求没有?这样页面加载速度非常快,并且它不会消耗任何cpu /内存。我只能在JSP中执行此操作,并且使用apache tomcat 6.

 ================= EDITED PART================

我通过实现application.getAttribute()/ setAttribute()说出了第一个解决方案..

 if(application.getAttribute(service)==null
 {
    //do first query
    application.setAttribute(service,name);
 } 
else name=application.getAttribute(service);

现在如何在第二个查询中使用id参数???请指教..

=============================================

String service=request.getParameter("service");

sqlstr = "SELECT uniqueid,name,body FROM tbl_texts WHERE 
serviceunique='"+service+"' AND webdomain='" + webdomain + "'";

  rs = DbUtils.getRs(con,sqlstr);
  if (rs.next()) {
  id = rs.getString("uniqueid");
  name = rs.getString("name");
  body=rs.getString("body");

  }
  rs.close();


  sqlstr = "SELECT animage,awidth,aheight FROM tbl_Images WHERE 
  uniqueid='" + id + " AND profile='" + imageprofile + "'";
   rs = DbUtils.getRs(con,sqlstr);
   if (rs.next()) {
    images = rs.getString("animage");
     size= (int)  (rs.getDouble(awidth) * rs.getDouble(rs.getDouble(aheight) )
   rs.close();

提前致谢!

1 个答案:

答案 0 :(得分:1)

首先,不要使用字符串连接来构建SQL查询。使用预备陈述。这是一个安全漏洞,没有理由错过这一点。

然后警告说,在JSP页面中使用Java代码被认为是不好的风格。这可能会导致无法维护的代码。在大多数情况下,最好遵守该规则。但要实事求是,有时在某些情况下最好打破这一规则。负责任的开发者应在平衡后确定利弊。

如果您决定将Java编写到JSP中,那么请正确执行。是安全的,使用预准备语句,验证输入参数(1000个char或null id是一个有效的id吗?)并同步并发访问。

作为穷人的缓存,您可以使用简单的Map实例(可能每个SQL查询一个)并将映射存储到应用程序范围中。使用同步访问和更改这些映射。

对于每个地图,创建一个参数类和一个结果类。

例如(使用Apache Commons Lang EqualsBuilderHashCodeBuilder):

class TextsParam {
  private String service;
  private String webdomain;

  // Getters and setters ...

  @Override 
  public boolean equals(Object obj) {
    if(obj == null) { return false; }
    if(obj == this) { return true; }
    if(obj.getClass() != getClass()) {
      return false;
    }
    TextsParam other = (TextsParam) obj;
    return new EqualsBuilder()
             .appendSuper(super.equals(obj))
             .append(service, other.service)
             .append(webdomain, other.webdomain)
             .isEquals();
  }

  @Override
  public int hashCode() {
    // you pick a hard-coded, randomly chosen, non-zero, odd number
    // ideally different for each class
    return new HashCodeBuilder(17, 37)
        .append(service)
        .append(webdomain).
        .toHashCode();
  }

}

class TextsResult {
  private String id;
  private String name;
  private String body;

  // Getters and setters ...
}

然后您的第一张地图可能是Map<TextsParam, TextsResult>类型。

在您的代码中,在您检查参数servicewebdomain不为空且有效后,使用这些参数创建TextsParam实例并检查您的地图是否已包含该密钥。如果是,请使用相应的TextsResult值。否则,执行数据库查询并将结果存储到地图中以供以后使用。不要忘记将该代码放入synchronized块(或更好的同步方法)。

请注意,添加到地图中的条目永远不会被删除。因此,这仅适用于可管理大小的可缓存值。下一步是使用Map实施,该实施会自动删除LRU cache之类的旧值。