Modelling improvements: inheritance + interfacing (Draft)

From: Lachlan Deck (lachlan.dec..mail.com)
Date: Sun May 27 2007 - 03:10:52 EDT

  • Next message: Aristedes Maniatis: "Re: Paging and SQL queries"

    Hi there,

    it's been my intention to follow this up for a while (having talked
    with Andrus about this in the past). Finally, due to necessity (via
    EOF), that time has come.

    Okay, so currently Cayenne supports one Single-table [a] inheritance.
    Below, I've outlined my suggestion for easily adding support for also
    modelling Horizontal [b] and Vertical [c] inheritance. And, as an
    added bonus, I also see the modelling of interfaces (at both DbEntity
    & ObjEntity layers) as another simple-yet-highly-useful addition to
    Cayenne.

    The good news, as far as I see it, is that these are simple additions
    to the data-map that in no way break existing models :-)

    With inheritance already in place, they ought to be reasonably simple
    to implement also. I'll be looking at submitting some patches over
    the next few weeks or so (with Ari's help) to realise these ideas
    (along with some extra docs for the wiki [p]) - but wanted to sound
    out these ideas first in order to see what additional areas of
    Cayenne will be effected by this. As I see it, these improvements are
    reasonably simple predominantly seeing as inheritance is already in
    place. I'm sure none of you need any convincing on the benefits of
    enhancing Cayenne's OO modelling concepts.

    Any objections? ;-)

    Note: the below descriptions are highly summarised (seeing as its
    intent is not to teach such concepts but to note the changes needed
    to cater for them). So if you need further clarification on anything
    feel free to ask.

    Plan of attack:
    - we'll be looking at submitting the xml changes (with validation
    adjustments) first along with the simple Db/ObjEntity additions.
    - afterwards, either if those who currently look after the swing
    modeller would like to be involved in adding the few widgets or we
    can do so.
    - See Lib changes below for more
    - other suggestions?

    with regards,

    --
    

    Lachlan Deck

    ---------------------------------- ---- Summary of XML Additions ---- ---------------------------------- 1) <obj-entity ...> needs the following additional (optional) xml attributes: - isAbstract="flag" - superRelationship="nameOfObjRelationship" to support [c] - isInterface="flag". 2) <obj-entity ...> needs to allow dbEntityName="" 3) <db-entity ...> needs an isInterface="flag" 4) <db-entity ...> needs to allow an optional child element <db- interface name="DbInterfaceName"/>

    That is the entirety of the xml additions that is needed to enable the whole gamut of both inheritance and interfacing/protocol modelling needs. Again, none of these break any current models out there in the wild. They're just optional extras.

    Naturally there'll need to be accompanying validation rules in the modelling tool for these (plus a couple of extra components such as a checkbox for isAbstract, isInterface, etc).

    More details....

    ---------------------------------- ----------- Interfacing ---------- ---------------------------------- Here's the needs as I see it: - allow optional DbEntity/ObjEntity interface/protocol definitions <db-entity isInterface="flag" ...> ... </db-entity> <obj-entity isInterface="flag" dbEntityName="DbEntityInterfaceName" ...> ... </obj-entity>

    - allow ObjEntity to simply be an interface without an associated DbEntity. <obj-entity isInterface="flag" dbEntityName="" ...> ... </obj-entity>

    - allow a DbEntity to implement other DbEntity interfaces (thereby defining attributes/relations once etc) <db-entity ...> ... <db-interface name="nameOfDbInterface" /> </db-entity>

    I'm not completely aware of what Cayenne's DataMap defaults (e.g., Schema defaults) offers but it appears to be global to the map and perhaps not as formal as the above. ---------------------------------- ----------- Inheritance ---------- ----------------------------------

    Naturally inheritance can be deep (i.e., multi-level) however the type of inheritance at each level is quite easily determined by the combination of the type of parent (if one exists, whether abstract and/or has a 'schema' definition etc) and the type of the child (whether it maps to the same table/view etc).

    There may be exceptions to the usual rule, where sub-entities do not redefine parent characteristics, but this should perhaps only be allowed for those times when the parent allows null for those fields. Otherwise perhaps the generated methods ought to be generated as final.

    summary of inheritance determinants (conceptually) as I see it... - isAbstract [d], [e] (optional for all types of inheritance) - determines if the parent can be instantiated - if false, for vertical inheritance requires declared qualifier [n] - does the parent map to a table/view? [f], [g] - Does the parent map to the same table/view as the Sub-entity? - yes: [a] - no: allows for [b] or [c] depending on whether parent is [f] or [g].

    Note #1: A DeclaredQualifier must be defined for [a] (current situation) and [c]+[e].

    Thus, for ObjEntities, we can easily define inheritance like so: - Vertical Inheritance [c] - parent: isAbstract="flag" (optionally true/false) dbEntityName="NonAbstractDbEntity1" - child: isAbstract="false" dbEntityName="NonAbstractDbEntity2" (optional) superRelationship="someRelationship" [o] declaredQualifier="..." (if parent not abstract) [n] - Horizontal Inheritance [b] - parent: isAbstract="flag" (optionally true/false) dbEntityName="" - cild: isAbstract="false" dbEntityName="NonAbstractDbEntity3" - Single-table Inheritance [a] - parent: isAbstract="flag" (optionally true/false) dbEntityName="NonAbstractDbEntity4" - cild: isAbstract="false" dbEntityName="NonAbstractDbEntity4" declaredQualifier="..."

    ---------------------------------- ----------- Lib Changes ---------- ---------------------------------- - fetching will be quite simple (naturally auto-constructing a qualifier based on the above conditions and fetching the attributes of the joined DbEntities). - Populating the results of the fetch to the entity won't be any different to the current methodology i would think. - primary key of super entity will propagate to child. Similarly (conceptually) simple. If you're using an EO_PK_SUPPORT table then checking for the next pk on the parent in that table (unless that doesn't yet exist in EO_PK_SUPPORT in which case you'd have to check the pk on each child initially). - resolving attributes from vertical inheritance will need to fault values from the parents DbEntity rather than as per normal.

    There might be other things but that seems to be the basic foundation.

    ---------------------------------- Footnotes ---------------------------------- Inheritance types: [a] Single-table (i.e., single table for entity hierarchy) [b] Horizontal (i.e., one table per sub-entity) [c] Vertical. See [n]. (i.e., one table per entity)

    ObjEntity concepts: [d] abstract ObjEntity [isAbstract="true"] [e] non-abstract ObjEntity [isAbstract="false", or implicit] [f] DbEntity-mapped ObjEntity [dbEntityName="SomeDbEntityName"] [g] DbEntity-less ObjEntity [dbEntityName=""] [h] Implied Inheritance: [superEntityName="ObjEntityName"] [i] Relational inheritance: [superRelationship="relationName" + <obj- relationship name="relationName" ... />] [j] ObjEntity interface: [isInterface="true", can inherit so long as parent is either [4] or [3]+[9]]

    DbEntity concepts: [k] schema-mapped DbEntity [explicit schema="SchemaName" or implicit from name] [l] schema-less DbEntity [isInterface="true"] [m] DbEntity implements [<interface name="DbInterfaceName" />]

    Notes: [n] when desiring to allow the instantiating/querying of the parent entity in vertical inheritance without also querying sub-entity traits: (i.e., [2]+[8] parent) [o] superRelationship is required to join on the primary key(s) of the source (sub-entity) and destination (parent entity) entities. Thus, dbEntityName is an optional xml attribute because the super entity name can be ascertained via the superRelationship's target entity. Additionally, the relationship ought not be generated as a public relationship (i.e., not be listed with getRelationships() but via getSuperRelationship()). [p] suggested extra headings/topics for (http://cayenne.apache.org/ doc/modeler-guide.html) with existing topics marked with '*' - Modelling Objects - Introduction - <... simple ...> - <... tutorial ...> - <... that builds ...> - <... and expands ...> - <... upon a basic idea ...> - <... utilising all of the below concepts ...> *- Modelling Database Layer - Schema contracts: interfaces - Introduction - Defining an interface - Adhering to an interface *- Modelling Object Layer - Modelling Interfaces - Introduction - Defining an interface - Adhering to an interface - Runtime * - Modelling Inheritance - Introduction - Differing Approaches - Design Decisions - Considerations - Horizontal Inheritance - Introduction - Mapping Horizontal Inheritance - Advantages of Horizontal Inheritance - Disadvantages of Horizontal Inheritance - Single-table Inheritance - Introduction - Mapping Horizontal Inheritance - Advantages of Single-table Inheritance - Disadvantages of Single-table Inheritance - Vertical Inheritance - Introduction - Mapping Vertical Inheritance - Advantages of Vertical Inheritance - Disadvantages of Vertical Inheritance



    This archive was generated by hypermail 2.0.0 : Sun May 27 2007 - 03:11:35 EDT