Cachemanager

Cacheonix support forum is dedicated to support requests, bug reports and feature suggestions.
vinod8b3
Posts: 4
Joined: Tue Nov 08, 2011 6:09 am

Cachemanager

Postby vinod8b3 » Tue Nov 08, 2011 6:20 am

Sir i have been executing the code given in the article for query optimisation using cache i have been doing a project regarding the same here is the code

there are two errors coming regarding unresolvable class cacheonix.cachemanager i dont know where to download that class i have downloaded the cacheonix .jar but that file is missing in the jar please look forward into this awaiting a kind and early response thanks regards here is the code..

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

public final class QueryKey implements Serializable {

private final String queryText;
private final List queryParameters;

public QueryKey(final String queryText, final List queryParameters) {
this.queryText = queryText;
this.queryParameters = queryParameters;
}

public String getQueryText() {
return queryText;
}

public List getQueryParameters() {
return Collections.unmodifiableList(queryParameters);
}

public boolean equals(final Object value) {
if (this == value) return true;
if (value == null || getClass() != value.getClass()) return false;
final QueryKey query = (QueryKey)value;
if (!queryParameters.equals(query.queryParameters)) return false;
if (!queryText.equals(query.queryText)) return false;
return true;
}


public int hashCode() {
int result;
result = queryText.hashCode();
result = 29 * result + queryParameters.hashCode();
return result;
}
}
The QueryResult object holds the results of executing the query:
import java.io.Serializable;
import java.util.List;

public final class QueryResult implements Serializable {

private final int columnCount;
private final List rows;


public QueryResult(final int columnCount, final List rows) {
this.columnCount = columnCount;
this.rows = rows;
}

public int getColumnCount() {
return columnCount;
}

public List getRows() {
return rows;
}
}

The following complete Java code shows a class responsible for caching the database queries for Java:
import java.io.IOException;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import cacheonix.cache.Cache;
import cacheonix.cache.CacheManager;

public final class CachingDatabaseQueryExecutor {

// Set up the database driver
private static final Driver driver;
static {
try {
final Class driverClass = Class.forName("my.database.drive.name");
driver = (Driver)driverClass.newInstance();
} catch (Exception) {
throw new IllegalStateException(e.toString());
}
}


public QueryResult execute(final String queryText, final List queryParameters)
throws IOException, ClassNotFoundException, IllegalAccessException,
InstantiationException, SQLException {

// Get result from cache
final Cache queryCache = CacheManager.getInstance().getCache("query.cache");
final QueryKey queryKey = new QueryKey(queryText, queryParameters);
QueryResult queryResult = (QueryResult)queryCache.get(queryKey);
if (queryResult == null) {
// Get the result from the database
final Connection conn = driver.connect("my/connection/URL",
new Properties());
final PreparedStatement ps = conn.prepareStatement(queryText);

// Set queryParameters
for (int i = 1; i <= queryParameters.size(); i++) {
final Object parameter = queryParameters.get(i - 1);
ps.setObject(i, parameter);
}

// Execute the statement and retrive the result
final List rows = new ArrayList(3);
final ResultSet rs = ps.executeQuery();
final int columnCount = rs.getMetaData().getColumnCount();
while (rs.next()) {
final Object[] row = new Object[columnCount];
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
row[columnIndex - 1] = rs.getObject(columnIndex);
}
}

// Create query result
queryResult = new QueryResult(columnCount, rows);

// Put the result to cache
queryCache.put(queryKey, queryResult);

}

return queryResult;
}
}

simeshev

Postby simeshev » Tue Nov 08, 2011 7:19 am

Hi Vinod,

Thanks for reporting this. The article has an outdated code. Please let us take care of it. We'll update this thread once the fix is in place.

Slava

simeshev

Postby simeshev » Tue Nov 08, 2011 7:41 am

Vinod,

We have updated the article code:

http://www.cacheonix.com/articles/Cachi ... n_Java.htm

Also, consider implementing Externalizable for QueryKey and QueryResult as described here:

http://wiki.cacheonix.com/display/CCHNX ... erformance

Let us know if you have any questions, we'll be happy to help.

Slava

vinod8b3
Posts: 4
Joined: Tue Nov 08, 2011 6:09 am

Postby vinod8b3 » Wed Nov 09, 2011 1:43 pm

Sir its very kind of your early reply.i have executed the code given in that link and i have a small doubt towards what should be assigned for querytext and queryparameters while i am writing a main class for executing the program .a small 2 query example will help me a lot in understanding the program preciselyand helps my research.Kindly u can mail me the examples @vinod8b3@gmail.com or post it here it would be very helpful

Thanks in advance

simeshev

Postby simeshev » Thu Nov 10, 2011 5:20 am

How about something like this:

String query = "select INVOICE_ID, INVOICE_NUMBER, INVOICE_DATA from INVOICES where INVOICE_ID=?";
List parameters = new ArrayList(1);
parameter.add(new Integer(1000));
CachingDatabaseQueryExecutor executor = new CachingDatabaseQueryExecutor();
QueryResult result = executor.execute(query, parameters);

mkaramanos

Caching Database Queries in Java - Article

Postby mkaramanos » Mon Dec 17, 2012 1:08 pm

Hi,

First of all i would like to congratulate all the team(s) for developing/supporting this framework, and i look forward to integrate it in my project.
Since i'm still trying to understand some key points of the framework, doubts are popping. One is regarding this article, and to be more precise, in the execute method. Should't the variable rows list store each row object and why is defined as final with size 3 since it will be passed as a parameter for a new QueryResult instance?

Other question is regarding the cache miss. In my case, for reporting purposes with large data being queried, the database(oracle) data is in constant update via store procedures(outside my scope), so lets suppose i cache the resultSets data, will be not synchronized with database until a cache miss is found. Or automatically, without user intervention, the cache updates it self, via certain configuration? What strategy do you recommend for cacheonix framework?

Best regards,
Michail

simeshev

Re: Caching Database Queries in Java - Article

Postby simeshev » Fri Dec 28, 2012 4:58 pm

mkaramanos wrote: Should't the variable rows list store each row object and why is defined as final with size 3 since it will be passed as a parameter for a new QueryResult instance?


You are right, it was a bug in the article code. We've fixed it:

http://www.cacheonix.com/articles/Cachi ... n_Java.htm


Slava

simeshev

Re: Caching Database Queries in Java - Article

Postby simeshev » Sat Dec 29, 2012 2:38 am

mkaramanos wrote:
Other question is regarding the cache miss. In my case, for reporting purposes with large data being queried, the database(oracle) data is in constant update via store procedures(outside my scope), so lets suppose i cache the resultSets data, will be not synchronized with database until a cache miss is found. Or automatically, without user intervention, the cache updates it self, via certain configuration? What strategy do you recommend for cacheonix framework?


The best way to handle the situation where the database updates may occur without Cacheonix knowing about it is to implement CacheInvalidator interface.

The implementation would consist of two changes:

1. Add a column to the database such that it is incremented every time the cached record or a table is modified. You can do it using a trigger.

2. Implement the CacheInvalidator interface. Here is an example using pseudo-code:

Code: Select all

/**
 * Invalidator of cache based on an incremental update counter (timestamp).
 * <p/>
 *
 * @author <a href="mailto:simeshev@cacheonix.com">Slava Imeshev</a>
 */
public final class TimestampCacheInvalidator implements CacheInvalidator {

   private static final String INVALIDATABLE_CACHE_NAME = "my.cache";

   private CacheInvalidatorContext context = null;

   private DatabaseConnector databaseConnector = null;


   /**
    * Sets the cache invalidator context. Cacheonix will call this method immediately after creating an instance of this
    * class that was provided to the cache configuration.
    *
    * @param context an instance of {@link CacheInvalidatorContext}
    */
   public void setContext(final CacheInvalidatorContext context) {

      this.context = context;
      final Properties contextProperties = context.getProperties();
      databaseConnector = new DatabaseConnector(contextProperties.getProperty("driver"),
              contextProperties.getProperty("url"), contextProperties.getProperty("user"),
              contextProperties.getProperty("password"));
   }


   /**
    * May invalidate the cache element. Cacheonix calls this method after locating a valid element requested by any read
    * methods of the cache.
    * <p/>
    * A class implementing  <code>CacheInvalidator</code>  decide sif the element has to be invalidated and calls {@link
    * Invalidateable#invalidate()} to mark the element as invalid. If the element is marked as invalid, Cacheonix will
    * evict it.
    *
    * @param cacheElement a cache element to invalidate.
    * @see Invalidateable#invalidate()
    */
   public void process(final Invalidateable cacheElement) {

      if (context.getCacheName().equals(INVALIDATABLE_CACHE_NAME)) {
         Connection conn = null;
         PreparedStatement ps = null;
         ResultSet rs = null;
         try {
            // Connect to the database
            conn = databaseConnector.connect();

            // Execute statement
            ps = conn.prepareStatement("select TIME_STAMP from INVOICE where ID = ?");
            final Integer invoiceID = (Integer) cacheElement.getKey();
            ps.setInt(1, invoiceID);
            rs = ps.executeQuery();

            // Check if the timestamps match
            if (rs.next()) {
               final int databaseTimestamp = rs.getInt(1);
               // Get the time stamp of the cached Invoice
               final Object value = cacheElement.getValue();
               final Invoice cachedInvoice = (Invoice) value;
               final int cachedInvoiceTimestamp = cachedInvoice.getTimeStamp();
               if (databaseTimestamp != cachedInvoiceTimestamp) {
                  // Time stamps do not match, exit
                  cacheElement.invalidate();
               }
            } else {
               // The record is gone. Invalidate the cache.
               cacheElement.invalidate();
            }
         } catch (StorageException e) {
            throw new IllegalArgumentException(e.toString());
         } catch (SQLException e) {
            cacheElement.invalidate();
         } finally {
            JDBCUtils.close(rs);
            JDBCUtils.close(ps);
            JDBCUtils.close(conn);
         }
      }
   }
}
[/code]

mkaramanos

Postby mkaramanos » Thu Jan 03, 2013 2:20 pm

Thanks for the clear solution and a happy new year to you all.

Best regards,
Michail


Return to “Cacheonix Support”

Who is online

Users browsing this forum: No registered users and 1 guest