Re: Status/Plans on Inheritance?

From: Andrus Adamchik (
Date: Mon Mar 03 2003 - 21:22:59 EST

  • Next message: Andrus Adamchik: "Re: PostgreSQL Failures"


    we are in the middle of the design process for inheritance. We planned
    to postpone implementation till 1.1, but since there is so much interest
    to this (see our recent posts), I suspect it will "just happen" even
    before 1.0 Beta :-)

    Here is a few links:



    Nevermind that (1) is called "Single Table Mapping", when combined with
    (2), it doesn't have to be just "single table"...

    Since original changes for (2) were only checked in yesterday, I guess
    what you saw in Cayenne before was "DerivedDbEntities". This wasn't
    exactly inheritance, just a way to define "runtime views" in the model.

    > - First problem is *who* decides from
    > the data-row which class to instanciate
    > for the data-object.
    > I put that as application code in the
    > data-object itself, by extending the
    > DataObject-interface by a method
    > "createNewInstance" (see attached file
    > "", with "Customer" and "Employee"
    > extending "Person")

    So you started implementing (1) "classIndicator" column. Very cool. But
    we stoped at this (mostly due to the time constraints), and you went
    way further down the design path ;-)

    > Instrumenting the methods
    > objectFromDataRow/registeredObject
    > in DataContext to call "createNewInstance"
    > ensures that the correct type is instanciated
    > if a data-row is available.

    Is this "createNewInstance" found in your Person class example? This
    maybe a good starting point. Later when such "class indicator" columsn
    will be supported in the DataMap (and the modeler), we should push such
    logic to the access layer (DataContext). I guess a compromize solution
    could be a static method in some utility class, so that everybody could
    you it without coding it over and over.

    > - Second problem is how to deal with
    > "Hollow" objects where the type is not
    > known. There are basically 2 solutions:
    > - the type is part of the ObjectId,
    > so it is always known
    > - or hollow objects with inheritance
    > are instances of the base-class,
    > but never "published"
    > I used the second solution. That means
    > a mechanism in "CayenneDataObject"
    > to refetch a Hollow object when it
    > is read via "readProperty"

    Good. Hollow objects of unknown type can only exist in relationships
    (otherwise an object was fetched somehow, and its class should've been
    determined). This means that such HOLLOW objects are not directly
    accessed by the application and can be resolved before an app gets a
    handle of such object.

    > - Third problem is how to "inherit"
    > the attributes and relationships
    > accross the "ObjEntity"'s.
    > I used a mechanism to copy
    > (after loading the map)
    > the attributes and relations down
    > the inheritance hirachies, so
    > that every instance of ObjEntity
    > has at runtime it's full list of
    > attributes and relationships.
    > (This is of course a *BAD* solution,
    > because this means
    > to use at runtime a different
    > representation of inheritance then
    > in the model - an indeed this needs
    > another workaround to prevent
    > the modeler from doing that and
    > destroying the mapping-file....
    > But the "correct" solution of
    > following the inheritance at
    > runtime (when getAttributeList()
    > is called) is probably more
    > work to implement and more
    > processing at runtime)

    If in addition to copying of attributes and relationships we add map
    change event notifications suggested by Holder recently, suddenly we get
    a clean implementation.

    > - fourth problem is to make the
    > queries quering the "superset"
    > of all attributes for all possible
    > types.
    > I did that by adding in ObjEntity
    > the "superset" list of attributes
    > and a method "getAttributeSuperSetList()"
    > that I called from within "SelectTranslator"
    > instead of "getAttributeList()"
    > (same for relations)

    So basically your superset works like that, right:

      A1 extends B extends C
      A2 extends B extends C
                 B1 extends C

    If there is a select query on "B", "superset" will contain a union of
    all extra attributes found in A1 and A2? Just making sure I understand
    this correctly.

    Just like in case with inherited attributes, such "superset" will be a
    runtime cache updated via events. So everything seems to fall in place.

    I guess you can start submitting patches :-). On the one hand I hate to
    see 1.0 slip some more, on the other hand this is something I personally
    need rather sooner than later. And then maybe there will be volunteers
    to integrate the patches sooner than I can possibly do?


    This archive was generated by hypermail 2.0.0 : Mon Mar 03 2003 - 21:24:33 EST