AW: CriteriaEnumeration

2007-03-12 Thread Thoralf Rickert
Hi Thomas,

Yes, you're right. It's similar to LargeSelect. But I think, it has two
advantages. With the correct combination of Criteria and
CriteriaPopulator I'm able to use doSelectJoinXXX and construct multiple
Torque objects at the same time (in my example this could be a store and
the corresponding address). The second advantage is, that it implements
the Enumeration interface and my opinion is, that this is more
comprehensible.

On the other side, the read-ahead-cache seems to be very useful and
could speed up some operations. It's more aware of DB specific problems
with databases that doesn't understand the offset/limit feature.

 This is more or less what LargeSelect does. I used to use it 
 for such things - reading data one page at a time. It 
 provides the additional advantage of a read-ahead-cache, 
 means it continues reading your data in the background while 
 you can process the first page of records.


 If you are interested, I created a small LargeSelectHelper 
 class which allows you to continuously read one page at a 
 time and let LargeSelect do the chunking.


Sorry, I'm not sure, what you mean?  Do you think, it would be better
for the CriteriaEnumeration to work with the LargeSelect?

bye
Thoralf


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: CriteriaEnumeration

2007-03-10 Thread Thomas Vandahl
Thoralf Rickert wrote:
 Hi!
 
 I'm not sure, if this was discussed before, but I want to send you this
 extension. 
 
 Currently I'm working on somekind of backup-procedure that reads some
 data from a database and creates a complex XML file (for example: stores
 with addresses and products). To do this, I have to get all stores
 from the database. If there are a lot of stores and I make just a
 doSelect(new Criteria()) I have (of course) trouble with the memory
 (number of stores  10).
 
 I could implement a special algorithm, but I decided to implement a
 mechanism that takes a Criteria and set offset/limit internally in a
 loop. In this way I can get 100 stores with one SELECT and do my work.
 If the pool is empty, I can read the next 100 stores.
 

This is more or less what LargeSelect does. I used to use it for such
things - reading data one page at a time. It provides the additional
advantage of a read-ahead-cache, means it continues reading your data
in the background while you can process the first page of records.

If you are interested, I created a small LargeSelectHelper class which
allows you to continuously read one page at a time and let LargeSelect
do the chunking.

Bye, Thomas.


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



CriteriaEnumeration

2007-03-09 Thread Thoralf Rickert
Hi!

I'm not sure, if this was discussed before, but I want to send you this
extension. 

Currently I'm working on somekind of backup-procedure that reads some
data from a database and creates a complex XML file (for example: stores
with addresses and products). To do this, I have to get all stores
from the database. If there are a lot of stores and I make just a
doSelect(new Criteria()) I have (of course) trouble with the memory
(number of stores  10).

I could implement a special algorithm, but I decided to implement a
mechanism that takes a Criteria and set offset/limit internally in a
loop. In this way I can get 100 stores with one SELECT and do my work.
If the pool is empty, I can read the next 100 stores.

I've enclosed this generic algorithm in a class called
CriteriaEnumeration:

---
public class CriteriaEnumerationE implements java.util.Enumeration {
  private static final Log log =
MyLog.getLogger(CriteriaEnumeration.class);
  private final java.util.VectorE fifo = new java.util.VectorE();
  
  private Criteria criteria = null;
  private CriteriaPopulatorE populator = null;
  private Connection connection = null;
  
  private int offset = 0;
  private int limit = 100;
  private boolean eot = false;
  private boolean useTransaction = false;

  /**
   * Sets the criteria for the Enumeration
   */
  public void setCriteria(Criteria criteria) {
this.criteria = criteria;
  }
  
  /**
   * Sets the populator that calls the database and creates the
   * Torque BaseObject
   */
  public void setPopulator(CriteriaPopulatorE populator) {
this.populator = populator;
  }
  
  /**
   * If true, the Enumeration uses a Transaction Connection
   * internally.
   */
  public void setTransaction(boolean useTransaction) {
this.useTransaction = useTransaction;
  }
  
  /**
   * Sets the size of the Buffer.
   */
  public void setLimit(int limit) {
this.limit = limit;
  }
  
  /**
   * @see java.util.Enumeration#hasMoreElements()
   */
  public boolean hasMoreElements() {
if (!fifo.isEmpty()) return true;
if (eot) return false;

criteria.setLimit(limit);
criteria.setOffset(offset);
offset+=limit;

if (useTransaction  connection == null) {
  try {
connection = Transaction.begin();
  } catch (Exception exception) {
log.error(Cannot use transactions.,exception);
connection = null;
  }
}

ListE elements = populator.getRows(connection,criteria);
if (Utilities.isEmpty(elements)) {
  eot = true;
  if (connection != null) {
try {
  Transaction.commit(connection);
} catch (Exception exception) {
  log.error(exception);
}
  }
}
if (eot) return false;

fifo.addAll(elements);

return true;
  }
  
  /**
   * @see java.util.Enumeration#nextElement()
   */
  public E nextElement() {
if (!hasMoreElements()) return null;
return fifo.remove(0);
  }
}
---

Note: This implementation uses a Transaction class that wraps the Torque
Transaction class

Also you need to implement a class that implements the interface
CriteriaPopulatorE

--
public interface CriteriaPopulatorE {
  public ListE getRows(Connection connection, Criteria criteria);
}
-

With this code you can iterate through the result without reading
everything at once. There are of course some problems. First the
database should accept offset and limit settings of the Criteria (like
MySQL). And second the data that you read should not change during the
enumeration. Of course there is a transaction-safe implementation, but
I'm not sure if it works in every environment. And of course this is
nothing for performance-junkies. ;-)


Here is an example with Stores

public class StorePeer extends BaseStorePeer {
  public static EnumerationStore getStores() {
Criteria criteria = new Criteria();
criteria.addAscendingOrderByColumn(ID);

CriteriaEnumerationStore enumeration = new
CriteriaEnumerationStore();
enumeration.setCriteria(criteria);
enumeration.setPopulator(new StorePopulator());
return enumeration;
  }

  static class StorePopulator implements CriteriaPopulatorStore {
public ListStore getRows(Connection connection, Criteria criteria)
{
  try {
log.debug(createQueryString(criteria));
return doSelectJoinAllExceptLogin(criteria,connection);
  } catch (Exception exception) {
log.error(exception);
return null;
  }
}
  }
}


bye
Thoralf


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]