Performing RecordStore Queries

Team-Fly

The real power of a database is being able to pull out just the record or records you want. In a larger database, this is called performing a query. In the RecordStore world, you use the enumerateRecords() method:

 public RecordEnumeration enumerateRecords(RecordFilter filter,     RecordComparator comparator, boolean keepUpdated)     throws RecordStoreNotOpenException 

This single method in RecordStore involves three different interfaces that you've never seen before. Let's start with the big picture first, and then drill down into the new interfaces.

The enumerateRecords() method returns a sorted subset of the records in a RecordStore. The RecordFilter determines which records will be included in the subset, while the RecordComparator is used to sort them. The returned RecordEnumeration allows you to navigate through the returned records.

RecordFilter

The simplest interface is RecordFilter. When you call enumerateRecords() on a RecordStore, each record's data is retrieved. RecordFilter has a single method, matches(), which is called for each record. A record filter should examine the record data and return true if the record should be included in the results returned from enumerateRecords().

Here's a simple RecordFilter implementation that will only select records whose first byte of data is 7:

 public class SevenFilter     implements javax.microedition.rms.RecordFilter {   public boolean matches(byte[] candidate) {     if (candidate.length == 0) return false;     return (candidate[0] == 7);   } } 

RecordComparator

The job of a RecordComparator implementation is to determine the order of two sets of record data. RecordComparator is similar to the java.util.Comparator interface in J2SE.

To implement the RecordComparator interface, you just need to define one method:

 public int compare(byte[] rec1, byte[] rec2) 

This method examines the data contained in rec1 and rec2 and determines which of them should come first in a sorted list. It should return one of the following constants defined in RecordComparator:

  • PRECEDES indicates that rec1 should come before rec2.

  • FOLLOWS indicates that rec1 should come after rec2.

  • EQUIVALENT signals that rec1 and rec2 are the same, at least as far as sorting is concerned.

The following simple implementation compares each byte of the given records and sorts them numerically. If the two records have the same data, up to the length of the shorter one, then they are deemed EQUIVALENT.

 public class SimpleComparator     implements javax.microedition.rms.RecordComparator {   public int compare(byte[] rec1, byte[] rec2) {     int limit = Math.min(rec1.length, rec2.length);     for (int index = 0; index < limit; index++) {       if (rec1[index] < rec2[index])         return PRECEDES;       else if (rec1[index] > rec2[index])         return FOLLOWS;     }     return EQUIVALENT;   } } 

Working with RecordEnumeration

RecordStore's enumerateRecords() method returns an implementation of the RecordEnumeration interface. RecordEnumeration is surprisingly complicated. Its basic function is to allow you to iterate through the records retrieved from the RecordStore. Unlike a regular J2SE Enumeration or Iterator, however, RecordEnumeration allows you to scroll through its contents both forward and backward. In addition, you can peek at the next or previous record ID. Finally, RecordEnumeration offers the possibility of keeping its data synchronized with the actual RecordStore. Behind the scenes, this is accomplished by registering the RecordEnumeration as a listener for RecordStore changes.

The basic operation of RecordEnumeration is to iterate through a set of records. You can find out if there's a next record by calling hasNextElement(). If the next record exists, you can retrieve its data by calling the following method:

 public byte[] nextRecord()     throws InvalidRecordIDException,            RecordStoreNotOpenException,            RecordStoreException 

Alternately, you can retrieve the next record's ID by calling this method:

 public int nextRecordId() throws InvalidRecordIDException 

You can't really have your cake and eat it, though; both nextRecord() and nextRecordId() advance the RecordEnumeration to the next record. If you want to retrieve both the ID and the data for the next record, you'd need to call nextRecordId() and then retrieve the record data directly from the RecordStore.

A typical use of RecordEnumeration would be to walk straight through the selected records, like this:

 // Open a RecordStore rs // Create a RecordFilter rf // Create a RecordComparator rc RecordEnumeration re = rs.enumerateRecords(rf, rc, false); while (re.hasNextElement()) {   byte[] recordBytes = re.nextRecord();   // Process the retrieved bytes. } 

As you're moving through the selected records, you can also move backward. RecordEnumeration includes hasPreviousElement(), previousRecord(), and previousRecordId() methods that work just their next counterparts.

Four out of the five ways to move the current position in the RecordEnumeration are the nextRecord(), nextRecordId(), previousRecord(), or previousRecordId() methods. The fifth method is kind of like a rewind button: reset() moves the record pointer back to the very beginning of the selected records.

When you're finished using a RecordEnumeration, you should release its resources. You can do this by calling destroy(), after which the RecordEnumeration is no longer usable.

Keeping a RecordEnumeration Up to Date

In a multithreaded environment, it's entirely possible that a RecordStore will change at the same time you're iterating through a RecordEnumeration for the same RecordStore. There are two ways to deal with this.

The first thing you can do is call rebuild(), which explicitly rebuilds the RecordEnumeration based on the RecordFilter and RecordComparator you originally specified.

The other possibility is to request a RecordEnumeration that is automatically updated with any changes to the underlying RecordStore. You can do this by passing true for the keepUpdated parameter of RecordStore's enumerateRecords() method. You can find out if the RecordEnumeration is automatically updated by calling isKeptUpdated(). Furthermore, you can change its state by calling keepUpdated().

Automatically updated RecordEnumerations register themselves as RecordListeners with the underlying RecordStore. Each time the RecordStore is changed, the RecordEnumeration is rebuilt. Keep in mind that this is an expensive operation (in terms of time), so if there are many RecordStore changes, you'll be paying a price for it.


Team-Fly


Wireless Java. Developing with J2ME
ColdFusion MX Professional Projects
ISBN: 1590590775
EAN: 2147483647
Year: 2000
Pages: 129

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net