Re: Patch to make SelectQueries work...

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Sun Apr 17 2005 - 21:25:27 EDT

  • Next message: Mike Kienenberger: "Re: [OS-JIRA] Resolved: (CAY-297) deadlock between commit and external event"

    Sweet!

    I am still tripping over Java 1.5 syntax so it took me a few minutes to
    understand the code. And I like it ;-)

    Now I'm thinking of a good way to integrate this approach in Cayenne
    API. Some sort of strategy parameter on a query... Or maybe keep query
    objects simple and instead introduce something similar to your
    QueryFactory... I'd call it QueryUtils (just like DataObjectUtils), but
    we have an old version of QueryUtils still around, so I am trying to
    think of another name...

    In the meantime feel free to upload any code that you can share to the
    Wiki examples area -
    http://objectstyle.org/confluence/display/CAY/Cayenne+Examples If you
    get a chance to do that, let me know your id - I'll give you the needed
    permissions.

    Thanks
    Andrus

    On Apr 17, 2005, at 7:20 PM, Mikaël Cluseau wrote:
    > Andrus,
    >
    > Here is the method I use to get the same behaviour. I use two queries
    > but it is still faster (in fact, .3 seconds for the request on primary
    > keys and 1.4 to get the full rows from the PKs, I don't really
    > understand why it is that slow -- but it is not done if objects are in
    > cache). I think it needs some work to be used in the real Cayenne,
    > because I didn't checked the strict equivalency in every case (in
    > particular, when the original query already gets customDbAttributes, or
    > the attributes I don't copy -- a clone method in query could be
    > useful).
    >
    > Notice that the QueryFactory factory used is home-made. Function names
    > are self-describing.
    >
    > public static <T extends DataObject> List<T> query(DataContext context,
    > Class<T> clazz, SelectQuery query, boolean fetchByPk) {
    > if (!fetchByPk) {
    > // Use the normal method
    > return query(context, clazz, query);
    > }
    > DbEntity entity = context.getEntityResolver().lookupDbEntity(clazz);
    >
    > // Copy the original query
    > SelectQuery query2 = new SelectQuery(clazz);
    > query2.setQualifier(query.getQualifier());
    > query2.addOrderings(query.getOrderings());
    > query2.setFetchLimit(query.getFetchLimit());
    >
    > // But modify the copy
    > query2.setDistinct(true);
    >
    > List<DbAttribute> attrs = entity.getPrimaryKey();
    > if (attrs.size() == 1) {
    > query2.addCustomDbAttribute(attrs.get(0).getName());
    > } else {
    > throw new UnsupportedOperationException(
    > "Unable to handle multi-columns (" + attrs.size()
    > + ") primary keys");
    > }
    >
    > // Performs the modified query
    > List results = context.performQuery(query2);
    >
    > if (results.isEmpty()) {
    > // Avoid useless pain
    > return new LinkedList<T>();
    > }
    >
    > List<T> cached = new LinkedList<T>();
    > Expression e;
    > if (attrs.size() == 1) {
    > List<Object> pks = new LinkedList<Object>();
    > final String name = attrs.get(0).getName();
    > for (Object o : results) {
    > Object pk = ((DataRow) o).get(name);
    > T cachedObj = clazz.cast(context.getObjectStore().getObject(
    > new ObjectId(clazz, name, pk)));
    > if (cachedObj == null) {
    > pks.add(pk);
    > } else {
    > cached.add(cachedObj);
    > }
    > }
    > e = QueryFactory.createIn("db:" + attrs.get(0).getName(), pks);
    > } else {
    > throw new UnsupportedOperationException(
    > "Unable to handle multi-columns (" + attrs.size()
    > + ") primary keys");
    > }
    >
    > if (e == null) {
    > // No expression => nothing to get
    > return cached;
    > }
    >
    > // Get full and real objects
    > List<T> retval = query(context, clazz, new SelectQuery(clazz, e));
    > // Ajout des objets en cache
    > if (!cached.isEmpty()) {
    > retval.addAll(cached);
    > }
    > // Sort the results
    > List<Ordering> orderings = query.getOrderings();
    > if (orderings != null && !orderings.isEmpty()) {
    > Collections.sort(retval, new CompositeComparator(orderings));
    > }
    > return retval;
    > }
    >
    > I did it on my spare time so you are free to use it as you want.



    This archive was generated by hypermail 2.0.0 : Sun Apr 17 2005 - 21:25:33 EDT