Re: Problem concerning Prefetching

From: Michael Gentry (blacknex..mail.com)
Date: Mon Jan 28 2008 - 11:02:49 EST

  • Next message: Jean-Paul Le Fèvre: "Re: Problem concerning Prefetching"

    Even with a one-to-many, Cayenne will still do the prefetches as
    shown. If you don't need everything at once, the batching idea
    suggested by Ari will probably be your best bet. Otherwise, you'll
    need to figure out a non-typical way of fetching the data which works
    right for your application. This normally isn't too difficult to do.
    Cayenne is great at the general case, but gives you the hooks to solve
    custom, non-typical problems when needed. Looking at your code, it
    looks like you do indeed want to fetch it all in.

    That being said, unless I'm missing something, you don't care too much
    about having the Galaxy itself -- you are just using it to obtain the
    properties, which is what you really want. Why not invert your query?
     This is off the top of my head and is unlikely to compile, but
    hopefully will make sense (note that you use the galaxy relationship
    here):

    public final List<GalaxyComponentProperties>
    selectGalaxyComponentProperties(int timestep)
    {
       StringBuffer buf = new StringBuffer("galaxy.halo.simulation.name = '");
       buf.append(getCurrentSimulationName());
       buf.append("' and galaxy.halo.properties.timestep = ");
       buf.append(timestep);

       Expression exp = Expression.fromString(buf.toString());
       SelectQuery query = new SelectQuery(GalaxyComponentProperties.class, exp);
    // fix this query.addOrdering("number", true);

       //query.addPrefetch("componentProperties");

       return (List<GalaxyComponentProperties>) performQuery(query);
    }

    props = handler.selectGalaxyComponentProperties(ts);

    for (GalaxyComponentProperties prop : props) {
    // GalaxyComponentProperties prop = g.getComponentProperties("disc");
       if (prop != null) {
           printer.println(g.getNumber() + ", " +
                           prop.getMassOfBaryons().toString());
       }
    }

    Also, since I tend to worry about security a bit, the following bit of
    code could allow for SQL injection (which is bad) if you are getting
    the data from an external source:

       StringBuffer buf = new StringBuffer("halo.simulation.name = '");
       buf.append(getCurrentSimulationName());
       buf.append("' and halo.properties.timestep = ");
       buf.append(timestep);

    It is much better to use bindings, such as:

        map = new HashMap(2);
        expression = Expression.fromString("halo.simulation.name =
    $simulationName and halo.properties.timestep = $timeStep");
        map.put("simulationName", getCurrentSimulationName());
        map.put("timeStep", new Integer(timestep));
        query = new SelectQuery(Galaxy.class, expression.expWithParameters(map));

    When using bindings, Cayenne (and the JDBC drivers) remove SQL
    injection as a security issue. When you construct the values
    yourself, it is less secure.

    Hope that helps,

    /dev/mrg

    On Jan 28, 2008 10:29 AM, Jean-Paul Le Fèvre <jean-paul.lefevr..ea.fr> wrote:
    > On Monday 28 January 2008, Michael Gentry wrote:
    > > Hi Jean-Paul,
    >
    > Hi Michael and Andrus,
    >
    > >
    > > It looks like galaxy -> galaxy_component_properties is a to-one
    > > relationship, which would cause Cayenne to issue multiple selects like
    > > this since it tries to resolve each fault individually.
    >
    > It's a one to many : each galaxy has 3 different types of properties.
    >
    > Here is the code (simplified) implementing my method :
    >
    > public final List<Galaxy> selectGalaxies(int timestep)
    > {
    > StringBuffer buf = new StringBuffer("halo.simulation.name = '");
    > buf.append(getCurrentSimulationName());
    > buf.append("' and halo.properties.timestep = ");
    > buf.append(timestep);
    >
    > Expression exp = Expression.fromString(buf.toString());
    > SelectQuery query = new SelectQuery(Galaxy.class, exp);
    > query.addOrdering("number", true);
    >
    > //query.addPrefetch("componentProperties");
    >
    > return (List<Galaxy>) performQuery(query);
    > }
    >
    > And here is how I use it :
    > galaxies = handler.selectGalaxies(ts);
    >
    > // Loop on galaxies, get the disc component and the mass of baryons.
    > for (Galaxy g : galaxies) {
    >
    > GalaxyComponentProperties prop = g.getComponentProperties("disc");
    > if (prop != null) {
    > printer.println(g.getNumber() + ", " +
    > prop.getMassOfBaryons().toString());
    > }
    > }
    >
    > >
    > > Given your manual SQL statement:
    > >
    > > select galaxies.number, galaxy_component_properties.mass_of_baryons
    > > from galaxy_component_properties
    > > join galaxies on galaxy_component_properties.galaxy_id = galaxies.id
    > > where some_clause
    > > order by galaxies.number;
    > >
    > > It looks like you don't actually care about having actual Cayenne
    > > objects (it looks like you only care about having two of the
    > > attributes)? If this is the case, you could use an SQLTemplate and
    > > raw data rows to only fetch in those two properties. If this isn't
    > > the case, let us know and we'll give you other ideas.
    >
    > In fact you asked the good question. I'm just at the beginning of the
    > development and I don't really know how the application will be used and as a
    > consequence it is hard to figure out what it the best strategy to implement
    > the functionalities : I guess that some users are only interested in
    > computing mean values, sums, min, max in big chunks of data but others want
    > to retrieve all the attributes of a small amount of specific objects. The
    > challenge is to make both types of users happy. I'm wondering whether it is
    > possible or not.
    > In my experience Cayenne has always been excellent at manipulating small
    > numbers of complex objects but, on the other hand, difficult to use on huge
    > dataset.
    >
    >
    >
    >
    > --
    > ___________________________________________________________________
    >
    > Jean-Paul Le Fèvre * Mail : LeFevr..onteny.org
    >
    >



    This archive was generated by hypermail 2.0.0 : Mon Jan 28 2008 - 11:03:22 EST