简体   繁体   中英

JSP Temporary storing Repetitive Database Results

I have a following code in JSP which runs repetitively each time user visits the page. The values of database result are same for all the visitors. This page takes parameter "service" and SQL query is performed based on it. The second SQL query is performed based on "id" generated by first query. If there are 20 different Services it runs the following queries 20 times and then only shows the page. So, is there any way how I can store these result temporarily (using cache or something) such that these queries are run only once/first visit and then for other request Database requests are not made?? such that the page loads very fast and it doesn't consume any cpu/memory.. I can only do this in JSP, and have apache tomcat 6.

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

I found first solution by implementing application.getAttribute()/setAttribute() saying..

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

Now how to use id parameter in second query??? Please advise..

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

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();

Thanks in advance!

First of all, don't use string concatenation to build your SQL queries. Use prepared statements. This is a security hole and there is no excuse to miss that point.

Then be warned that it is considered bad style to use Java code inside JSP pages. This may lead to unmaintainable code. In the majority of cases it is best to stick by that rule. But to be realistic, sometimes under some circumstances it is best to break that rule. The responsible developer should decide after balance pros and cons.

If you decide to write Java into your JSP then do it right. Be secure, use prepared statements, validate your input parameters (is a 1000 char or null id a valid id?) and synchronize concurrent access.

As a poor man's cache you can use simple Map instances (maybe one for each SQL query) and store the maps into application scope. Use synchronization to access and change these maps.

For each map create a parameter class and a result class.

For example (with Apache Commons Lang EqualsBuilder and HashCodeBuilder ):

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 ...
}

Then your first map could be of type Map<TextsParam, TextsResult> .

In your code, after you checked that parameters service and webdomain are not null and valid, you create a TextsParam instance with these parameters and check if your map already contains that key. If yes, use the corresponding TextsResult value. Otherwise execute the database query and store the result in to your map for later use. Don't forget to put that code into a synchronized block (or better a synchronized method).

Be aware that an entry added to your map will never be deleted. So this will work only for a manageable size of cachable values. The next step would be to use a Map implementation which automatically removes old values like a LRU cache .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM