Re: abstract entities, inheritance, etc.

From: Robert Zeigler (robert.zeigle..oxanemy.com)
Date: Thu Apr 23 2009 - 19:53:12 EDT

  • Next message: Aristedes Maniatis: "Re: abstract entities, inheritance, etc."

    On Apr 23, 2009, at 4/236:32 PM , Aristedes Maniatis wrote:

    >
    > On 24/04/2009, at 9:17 AM, Robert Zeigler wrote:
    >
    >> So, I was playing around a bit with the "is abstract" flag on
    >> abstract entities.
    >> I confess that it didn't quite work the way I thought it would.
    >> For one, the superclass was abstract, but not the subclass.
    >
    > That is the common situation when you want horizontal inheritance. [1]

    Right, which is why I'm surprised at the current generated classes,
    but I need to be more specific.

    I have:

                                 Entry (abstract)
    ProjectNote (concrete) ProtocolRun(concrete)

    So I checked the "isabstract" for Entity. The result of class
    generation was:

    in package xxx.auto:
    public abstract class _Entry{}
    public class _ProjectNote{}
    public class _ProtocolRun{}

    in package xxx:
    public class Entry{} //<-- this is what I found surprising
    public class ProjectNote{}
    public class ProtocolRun{}

    I expected the Entry subclass of _Entry, and superclass of the other
    two concrete classes to be abstract. Instead, only the
    cayenne-"managed" superclass was abstract.
    It seems like there's very little point to that: nobody is going to
    try to directly instantiate _Entry, anyway. And I can't put abstract
    methods that subclasses should implement into _Entry, since they'll be
    lost on class regeneration. I guess it's a matter of expectations: by
    checking "isabstract", I expect cayenne to treat that object entity as
    abstract... and not try to instantiate it. :)

    >
    >> I went ahead and made the subclass abstract. Which raises the
    >> second issue. I have two obj entities entities extending the
    >> "abstract" superclass, using a single discriminator column. I went
    >> to query the base class (ala: select e from Entry e), and the query
    >> failed, due to the inability to instantiate an instance of Entry.
    >> Evidently, cayenne is trying to instantiate all of the subclasses
    >> instances as instances of the superclass. Shouldn't cayenne be
    >> instantiating the subclasses?
    >
    > EOF has a switch for this called something like 'deep object
    > resolution'. That is, when you query Artist.class, should you get
    > back a list of Painter.class, Photographer.class, etc object (as you
    > are expecting), or get back a list of Artist objects. Each can be
    > useful in different situations, particularly since just returning
    > Artist objects means less work for the database (fewer JOINs).
    >
    > Obviously if your query was for Painter.class then you will only get
    > Painter objects back.
    >
    >> Put another way, what is the technical reason that cayenne /isn't/
    >> instantiating the subclasses as instances of the subclasses? Given
    >> the potential of polymorphism, it seems like instantiating as the
    >> superclass, even if the superclass is concrete, is incorrect
    >> behavior? Just trying to clarify, here. I'll be digging through
    >> the code to try to understand the specifics of how cayenne handles
    >> inheritance, but, any pointers appreciated.
    >
    > I think ultimately we need both behaviours.
    >

    Fair enough that, for performance reasons, you might want only the
    superclass.
    But then... if you're using horizontal inheritance ("table per
    concrete class"), for example, you already need to fetch from both
    tables if you perform a query for the superclass; I'm trying to think
    of an instance when you would be performing a superclass query and /
    not/ have the type information at hand... ok, vertical inheritance,
    you might not have the type information. :) In terms of additional
    joins to fetch additional information... we already have lazy loading
    of relationships; it seems like it should be possible to lazy-load the
    attributes, as well, at least for queries on the superclass, saving
    the hassle of additional joins... I think the only place where you
    would have additional joins is vertical inheritance, anyway... and, I
    suppose, if a subclass has a flattened property not present in the
    parent class.

    Anyway, not opposed to keeping the option of the current behavior, but
    definitely +1 for resolving to the subclass level. It'll be necessary
    to properly support horizontal inheritance.

    Robert



    This archive was generated by hypermail 2.0.0 : Thu Apr 23 2009 - 19:54:05 EDT