Grokbase Groups Cayenne dev May 2007
FAQ
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

Search Discussions

  • Andrus Adamchik at May 29, 2007 at 9:46 am
    Hi Lachlan,

    I appreciate you driving this discussion. Vertical inheritance
    implementation is long overdue.

    I'll write a separate email about inheritance, but do you think we
    can split the discussion in two - interfaces and inheritance being
    separate independent features. I am still trying to think over what
    you are proposing in regards to the interfaces, and combining it with
    inheritance discussion only complicates things. Or is there a reason
    we would like to keep them together?

    Thanks
    Andrus

    On May 27, 2007, at 10:10 AM, Lachlan Deck wrote:

    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
  • Lachlan Deck at May 30, 2007 at 4:16 am

    On 29/05/2007, at 7:46 PM, Andrus Adamchik wrote:

    Hi Lachlan,

    I appreciate you driving this discussion. Vertical inheritance
    implementation is long overdue.
    Great and after having thought through it for quite a bit it seems to
    me that it's a reasonably simple step forward too.
    I'll write a separate email about inheritance, but do you think we
    can split the discussion in two - interfaces and inheritance being
    separate independent features. I am still trying to think over what
    you are proposing in regards to the interfaces, and combining it
    with inheritance discussion only complicates things.
    Sure. No problems.
    Or is there a reason we would like to keep them together?
    Not really. Except that an interface can inherit/extend from another
    one. So that would make the feature for adding interfaces dependent
    on inheritance.

    with regards,
    --

    Lachlan Deck
  • Andrus Adamchik at May 29, 2007 at 10:02 am
    Trying to decompose it further (so that we could Jira individual
    chunks easily :-))... +1 for the abstract entities support, but they
    can also be implemented as a separate feature independent from
    inheritance per se.

    <obj-entity ...> needs the following additional (optional) xml
    attributes:
    - isAbstract="flag"
    +1

    Also the following steps will be needed:

    * Modeler checkbox for ObjEntity "abstract" flag
    * Changes to the code generation templates to generate abstract java
    classes for such entities
    * Changes to the validation rules to allow ObjEntity with no db
    entity for abstract entities

    * maybe also some runtime checks for abstract entity (???)

    Thanks
    Andrus


    On May 27, 2007, at 10:10 AM, Lachlan Deck wrote:

    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
  • Andrus Adamchik at May 29, 2007 at 1:02 pm
    Ok, I overlooked the issue of DB mapping of abstract entities that do
    not have a DbEntity. IIRC this issue was raised when we discussed
    embeddables. Not sure we came to any conclusion back then. So is this
    what proposed "DbEntity interfaces" are for? Maybe we can simplify
    that and continue mapping abstract attributes (be for abstract
    ObjEntities or Embeddables) by simply specifying a "db attribute
    name", allowing to override it in a concrete definition? This is very
    close to how JPA suggests to do it, would cut down on the separate
    interface definitions, and allow to reuse the existing XML format
    without change (except for "isAbstract" flag).

    What do you think?

    Andrus



    On May 29, 2007, at 1:01 PM, Andrus Adamchik wrote:

    Trying to decompose it further (so that we could Jira individual
    chunks easily :-))... +1 for the abstract entities support, but
    they can also be implemented as a separate feature independent from
    inheritance per se.

    <obj-entity ...> needs the following additional (optional) xml
    attributes:
    - isAbstract="flag"
    +1

    Also the following steps will be needed:

    * Modeler checkbox for ObjEntity "abstract" flag
    * Changes to the code generation templates to generate abstract
    java classes for such entities
    * Changes to the validation rules to allow ObjEntity with no db
    entity for abstract entities

    * maybe also some runtime checks for abstract entity (???)

    Thanks
    Andrus
  • Lachlan Deck at May 30, 2007 at 5:05 am

    On 29/05/2007, at 11:02 PM, Andrus Adamchik wrote:

    Ok, I overlooked the issue of DB mapping of abstract entities that
    do not have a DbEntity. IIRC this issue was raised when we
    discussed embeddables. Not sure we came to any conclusion back
    then. So is this what proposed "DbEntity interfaces" are for?
    I'm not familiar with the embeddable discussion but this is the idea
    of DbEntity interfaces:
    a) you have a series of DbEntities that are not inherited in any way
    but for which you want them to conform to an interface 'A'. They are
    explicitly tied to that interface (rather than having to synchronise
    to it). i.e., the attributes/relations appear as they do for
    inherited characteristics. i.e., they're defined once per model and
    implemented by various other DbEntities.

    b) an ObjEntity interface 'a' may optionally map to a DbEntity
    interface 'b'. Any ObjEntity 'c' that maps to a DbEntity that
    implements 'b' will be shown to implicitly implement the associated
    ObjEntity 'a'.

    c) then there are the ObjEntity interfaces that have no associated
    DbEntity interface...
    Maybe we can simplify that and continue mapping abstract attributes
    (be for abstract ObjEntities or Embeddables) by simply specifying a
    "db attribute name", allowing to override it in a concrete
    definition? This is very close to how JPA suggests to do it, would
    cut down on the separate interface definitions, and allow to reuse
    the existing XML format without change (except for "isAbstract" flag).

    What do you think?
    Sounds like a supporting concept. i.e., an interface provides for a
    specification that includes attributes x, y, & z with certain
    constraints.

    An abstract attribute on its own would be useful within an interface.

    with regards,
    --

    Lachlan Deck
  • Andrus Adamchik at May 30, 2007 at 9:18 am

    On May 30, 2007, at 8:04 AM, Lachlan Deck wrote:

    I'm not familiar with the embeddable discussion but this is the
    idea of DbEntity interfaces:
    a) you have a series of DbEntities that are not inherited in any
    way but for which you want them to conform to an interface 'A'.
    They are explicitly tied to that interface (rather than having to
    synchronise to it). i.e., the attributes/relations appear as they
    do for inherited characteristics. i.e., they're defined once per
    model and implemented by various other DbEntities.

    b) an ObjEntity interface 'a' may optionally map to a DbEntity
    interface 'b'. Any ObjEntity 'c' that maps to a DbEntity that
    implements 'b' will be shown to implicitly implement the associated
    ObjEntity 'a'.

    c) then there are the ObjEntity interfaces that have no associated
    DbEntity interface...

    Hi Lachlan,

    What I am concerned about with DbEntity interfaces is that DbEntities
    model database tables and there is no interface concept in DB world.
    So I still don't understand why we need DbEntity inheritance? Could
    you please elaborate or give some examples?

    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables. So is it worth complicating
    the mapping by introducing a concept with no analog in the DB world?
    My suspicion is that it will be very hard to explain to the users.

    Andrus
  • Andrus Adamchik at May 30, 2007 at 9:26 am

    On May 30, 2007, at 12:16 PM, Andrus Adamchik wrote:

    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables. So is it worth
    complicating the mapping by introducing a concept with no analog in
    the DB world? My suspicion is that it will be very hard to explain
    to the users.
    More on coincidental part. It will only occur in denormalized
    schemas, as DB "schema reuse" is done via normalization. So it is an
    edge case.

    Andrus
  • Aristedes Maniatis at May 30, 2007 at 9:33 am

    On 30/05/2007, at 7:16 PM, Andrus Adamchik wrote:

    What I am concerned about with DbEntity interfaces is that
    DbEntities model database tables and there is no interface concept
    in DB world. So I still don't understand why we need DbEntity
    inheritance? Could you please elaborate or give some examples?

    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables. So is it worth
    complicating the mapping by introducing a concept with no analog in
    the DB world? My suspicion is that it will be very hard to explain
    to the users.
    Perhaps 'interface' is just the wrong word. The idea is similar to
    the WO prototype idea and the most common example is 'money' - you
    can define a money type once as having scale=2 and then just use that
    in all the dbEntity attributes.

    Interfaces in ObjEntities are completely different things again. They
    create actual interfaces in the Java classes. Perhaps we should also
    shed some of these extra ideas for now and focus on the main goals:

    1. abstract classes
    2. horizontal inheritance (where dbEntity=NULL for an objEntity)
    3. vertical inheritance (where a special ObjRelationship is created
    to specify the superclass. There may also need to be a qualifier like
    with single table - Lachlan thinks yes, I'm dubious.)

    I believe that is the right order to implement the ideas (easiest to
    hardest).



    Simultaneously we can work on interfaces. This has two steps:

    1. implement interfaces in the modeller, XML, datamap and class
    templates but have no runtime code in Cayenne for them. This is very
    easy and quite useful on its own.
    2. implement the ability for SelectQuery to return a mixture of
    objEntities based on a query of the interface

    They don't really overlap that much except that some of the issues
    faced in making queries work may be applicable to both interfaces and
    inheritance.


    Finally we have dbEntity interfaces (prototypes) which maybe need
    another name and are something different again, but maybe we can cut
    them out of this whole conversation and return to them later?
    Lachlan, can we drop this one for now?


    Ari


    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Andrus Adamchik at May 30, 2007 at 9:44 am
    Yes, "prototype" is a much better word, and such change in
    terminology is very important for this discussion to go forward, as
    "interface" has a very specific meaning in OO development. Let's
    definitely discuss it separately from the inheritance.

    Andrus

    On May 30, 2007, at 12:32 PM, Aristedes Maniatis wrote:

    On 30/05/2007, at 7:16 PM, Andrus Adamchik wrote:

    What I am concerned about with DbEntity interfaces is that
    DbEntities model database tables and there is no interface concept
    in DB world. So I still don't understand why we need DbEntity
    inheritance? Could you please elaborate or give some examples?

    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables. So is it worth
    complicating the mapping by introducing a concept with no analog
    in the DB world? My suspicion is that it will be very hard to
    explain to the users.
    Perhaps 'interface' is just the wrong word. The idea is similar to
    the WO prototype idea and the most common example is 'money' - you
    can define a money type once as having scale=2 and then just use
    that in all the dbEntity attributes.

    Interfaces in ObjEntities are completely different things again.
    They create actual interfaces in the Java classes. Perhaps we
    should also shed some of these extra ideas for now and focus on the
    main goals:

    1. abstract classes
    2. horizontal inheritance (where dbEntity=NULL for an objEntity)
    3. vertical inheritance (where a special ObjRelationship is created
    to specify the superclass. There may also need to be a qualifier
    like with single table - Lachlan thinks yes, I'm dubious.)

    I believe that is the right order to implement the ideas (easiest
    to hardest).



    Simultaneously we can work on interfaces. This has two steps:

    1. implement interfaces in the modeller, XML, datamap and class
    templates but have no runtime code in Cayenne for them. This is
    very easy and quite useful on its own.
    2. implement the ability for SelectQuery to return a mixture of
    objEntities based on a query of the interface

    They don't really overlap that much except that some of the issues
    faced in making queries work may be applicable to both interfaces
    and inheritance.


    Finally we have dbEntity interfaces (prototypes) which maybe need
    another name and are something different again, but maybe we can
    cut them out of this whole conversation and return to them later?
    Lachlan, can we drop this one for now?


    Ari


    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Mike Kienenberger at May 30, 2007 at 3:15 pm
    Note that we already have open JIRA issues on creating prototypes.
    It's just that no one's gotten around to implementing it yet. For
    example,

    https://issues.apache.org/cayenne/browse/CAY-225

    On 5/30/07, Andrus Adamchik wrote:
    Yes, "prototype" is a much better word, and such change in
    terminology is very important for this discussion to go forward, as
    "interface" has a very specific meaning in OO development. Let's
    definitely discuss it separately from the inheritance.

    Andrus

    On May 30, 2007, at 12:32 PM, Aristedes Maniatis wrote:

    On 30/05/2007, at 7:16 PM, Andrus Adamchik wrote:

    What I am concerned about with DbEntity interfaces is that
    DbEntities model database tables and there is no interface concept
    in DB world. So I still don't understand why we need DbEntity
    inheritance? Could you please elaborate or give some examples?

    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables. So is it worth
    complicating the mapping by introducing a concept with no analog
    in the DB world? My suspicion is that it will be very hard to
    explain to the users.
    Perhaps 'interface' is just the wrong word. The idea is similar to
    the WO prototype idea and the most common example is 'money' - you
    can define a money type once as having scale=2 and then just use
    that in all the dbEntity attributes.

    Interfaces in ObjEntities are completely different things again.
    They create actual interfaces in the Java classes. Perhaps we
    should also shed some of these extra ideas for now and focus on the
    main goals:

    1. abstract classes
    2. horizontal inheritance (where dbEntity=NULL for an objEntity)
    3. vertical inheritance (where a special ObjRelationship is created
    to specify the superclass. There may also need to be a qualifier
    like with single table - Lachlan thinks yes, I'm dubious.)

    I believe that is the right order to implement the ideas (easiest
    to hardest).



    Simultaneously we can work on interfaces. This has two steps:

    1. implement interfaces in the modeller, XML, datamap and class
    templates but have no runtime code in Cayenne for them. This is
    very easy and quite useful on its own.
    2. implement the ability for SelectQuery to return a mixture of
    objEntities based on a query of the interface

    They don't really overlap that much except that some of the issues
    faced in making queries work may be applicable to both interfaces
    and inheritance.


    Finally we have dbEntity interfaces (prototypes) which maybe need
    another name and are something different again, but maybe we can
    cut them out of this whole conversation and return to them later?
    Lachlan, can we drop this one for now?


    Ari


    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Lachlan Deck at May 30, 2007 at 8:19 pm

    On 30/05/2007, at 7:32 PM, Aristedes Maniatis wrote:
    On 30/05/2007, at 7:16 PM, Andrus Adamchik wrote:

    What I am concerned about with DbEntity interfaces is that
    DbEntities model database tables and there is no interface concept
    in DB world. So I still don't understand why we need DbEntity
    inheritance? Could you please elaborate or give some examples?

    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables. So is it worth
    complicating the mapping by introducing a concept with no analog
    in the DB world? My suspicion is that it will be very hard to
    explain to the users.
    Perhaps 'interface' is just the wrong word. The idea is similar to
    the WO prototype idea and the most common example is 'money'
    No. This is not an attribute prototyping schema. The EOF EO[Adaptor]
    Prototypes is more akin to the embeddables concept.

    I'm specifically talking about interfaces which is the definition of
    a protocol that an entity adheres to. Prototypes, in contrast, are
    aimed towards prototyping individual attributes.

    with regards,
    --

    Lachlan Deck
  • Lachlan Deck at May 30, 2007 at 8:46 pm

    On 30/05/2007, at 7:32 PM, Aristedes Maniatis wrote:

    3. vertical inheritance (where a special ObjRelationship is created
    to specify the superclass. There may also need to be a qualifier
    like with single table - Lachlan thinks yes, I'm dubious.)
    The qualifier is required for vertical inheritance only for the case
    where it is permitted to instantiate objects of the parent entity. It
    is not necessary when the parent entity is abstract.

    When the parent entity is not abstract and you are following a
    relationship from another entity to the parent entity, as one
    example, and you want to filter out all but 'employee' and 'student'
    types this allows Cayenne to fetch such objects without also having
    to query the sub-type characteristics. In addition, determining what
    the global object id is for when figuring out what type of sub-entity
    the parent belongs to should you wish to turn it back into the subclass.

    I believe it is asking for a much more complicated implementation
    without the declared qualifier for vertical inheritance when the
    parent is not abstract.

    with regards,
    --

    Lachlan Deck
  • Lachlan Deck at May 30, 2007 at 9:31 pm

    On 30/05/2007, at 7:16 PM, Andrus Adamchik wrote:
    On May 30, 2007, at 8:04 AM, Lachlan Deck wrote:

    I'm not familiar with the embeddable discussion but this is the
    idea of DbEntity interfaces:
    a) you have a series of DbEntities that are not inherited in any
    way but for which you want them to conform to an interface 'A'.
    They are explicitly tied to that interface (rather than having to
    synchronise to it). i.e., the attributes/relations appear as they
    do for inherited characteristics. i.e., they're defined once per
    model and implemented by various other DbEntities.

    b) an ObjEntity interface 'a' may optionally map to a DbEntity
    interface 'b'. Any ObjEntity 'c' that maps to a DbEntity that
    implements 'b' will be shown to implicitly implement the
    associated ObjEntity 'a'.

    c) then there are the ObjEntity interfaces that have no associated
    DbEntity interface...
    What I am concerned about with DbEntity interfaces is that
    DbEntities model database tables and there is no interface concept
    in DB world. So I still don't understand why we need DbEntity
    inheritance? Could you please elaborate or give some examples?
    There's no need for DbEntity inheritance per se. But interfaces can
    extend other interfaces. These DbEntity interfaces also have
    ObjEntity equivalents. (see below)
    The only use I can see for it is a *coincidental* match between
    groups of attributes in multiple tables.
    In terms of the generated sql, and so far as the database is
    concerned, that is correct. However, when we're talking about an
    enterprise mapping tool, where business/application logic/constraints
    are defined (and exported to a database, java code, the runtime
    environment, etc), then I think it's a valid concept that 'makes sense'.

    i.e., in terms of the developers application of such a schema,
    interfaces seem to me to be a natural modelling task.
    So is it worth complicating the mapping by introducing a concept
    with no analog in the DB world? My suspicion is that it will be
    very hard to explain to the users.
    I wouldn't have thought it would be a difficult concept to grasp. But
    perhaps I need to provide a better use-case.

    We have a web application that contains numerous entities. Most of
    these are populated via soap from numerous remote applications. In
    order to support the integrity of such replication each entity
    adheres to a simple (though currently imaginary) interface:
    Replicatable.

    Now you might say 'well you can just create an ObjEntity interface to
    create the appropriate java interfaces'. Of course that is true,
    however for mine that is approaching the problem backwards and
    requires more work and more accidental DbEntity mapping in the first
    place seeing as this particular interface requires each entity to
    persistently store certain data. The natural order of such mapping
    begins with the DbEntity layer where each entity needs to adhere to
    this protocol. Each ObjEntity counterpart will similarly validate to
    implement the counterpart ObjEntity interfaces of the DbEntity
    interface.

    Let's say that a sub-set of these entities need to adhere to an
    additional, yet supporting, protocol. Thus the need for interface
    inheritance on the Db layer.

    Let's say that, later on, we need to change the interface (e.g.,
    adding two more fields). With what I'm suggesting the change is
    simple, almost one-click. i.e., change the db-entity interface,
    synchronise the ObjEntity interface with it, save the model,
    regenerate classes etc. Without the interface in the Db layer it
    requires copy/paste for each and every db entity and so on... as I
    mentioned that's more work and for mine, less logical :-)

    The main purpose of this concept is the logical mapping of
    application-logic into a medium that has no such knowledge.

    Of course, there are going to be times when someone may wish to map
    an ObjEntity interface that has no Db counterpart. That is an
    additional option seeing as with the inheritance concepts we're
    allowing ObjEntity to have dbEntityName="".

    Does that clarify where this concept is coming from? Personally, I
    think this would take the enterprise mapping to another level.

    with regards,
    --

    Lachlan Deck
  • Lachlan Deck at May 30, 2007 at 8:14 pm

    On 30/05/2007, at 3:04 PM, Lachlan Deck wrote:
    On 29/05/2007, at 11:02 PM, Andrus Adamchik wrote:

    Ok, I overlooked the issue of DB mapping of abstract entities that
    do not have a DbEntity. IIRC this issue was raised when we
    discussed embeddables. Not sure we came to any conclusion back
    then. So is this what proposed "DbEntity interfaces" are for?
    I'm not familiar with the embeddable discussion but this is the
    idea of DbEntity interfaces:
    a) you have a series of DbEntities that are not inherited in any
    way but for which you want them to conform to an interface 'A'.
    They are explicitly tied to that interface (rather than having to
    synchronise to it). i.e., the attributes/relations appear as they
    do for inherited characteristics. i.e., they're defined once per
    model and implemented by various other DbEntities.

    b) an ObjEntity interface 'a' may optionally map to a DbEntity
    interface 'b'. Any ObjEntity 'c' that maps to a DbEntity that
    implements 'b' will be shown to implicitly implement the associated
    ObjEntity 'a'.

    c) then there are the ObjEntity interfaces that have no associated
    DbEntity interface...
    Maybe we can simplify that and continue mapping abstract
    attributes (be for abstract ObjEntities or Embeddables) by simply
    specifying a "db attribute name", allowing to override it in a
    concrete definition? This is very close to how JPA suggests to do
    it, would cut down on the separate interface definitions, and
    allow to reuse the existing XML format without change (except for
    "isAbstract" flag).
    On further reflection, isn't that concept similar to the EOF's EO
    [Adaptor]Prototypes? i.e., defining abstract attributes (e.g.,
    nameField_varchar(64)) that can be utilised by various non-abstract
    attributes in any DbEntity.

    The concept I'm suggesting, however, allows a protocol to be defined
    that a DbEntity adheres to rather than an individual attribute. Such
    protocols, of course, can, via inheritance, be the combination of a
    few interfaces.
    Sounds like a supporting concept. i.e., an interface provides for a
    specification that includes attributes x, y, & z with certain
    constraints.

    An abstract attribute on its own would be useful within an interface.
    with regards,
    --

    Lachlan Deck
  • Lachlan Deck at May 30, 2007 at 4:28 am

    On 29/05/2007, at 8:01 PM, Andrus Adamchik wrote:

    Trying to decompose it further (so that we could Jira individual
    chunks easily :-))... +1 for the abstract entities support, but
    they can also be implemented as a separate feature independent from
    inheritance per se.
    True.
    <obj-entity ...> needs the following additional (optional) xml
    attributes:
    - isAbstract="flag"
    +1

    Also the following steps will be needed:

    * Modeler checkbox for ObjEntity "abstract" flag
    * Changes to the code generation templates to generate abstract
    java classes for such entities Yep.
    * Changes to the validation rules to allow ObjEntity with no db
    entity for abstract entities
    The question of 'isAbstract' is merely a question of 'can instances
    of this entity be instantiated'?

    Certainly changes to validation rules are necessary. But it is
    possible for an entity to be both abstract whilst having an
    associated db entity (e.g., vertical inheritance where the developer
    doesn't desire to instantiate instances of parent entity).
    * maybe also some runtime checks for abstract entity (???)
    The only runtime checks I can foresee at the moment are:
    - a CayenneRuntimeException for attempting to do a fetch on an
    ObjEntity that has no associated db entity.

    Other logic will need to be in place that determines how deep the
    fetch is. e.g., if there's a SelectQuery on a parent entity that's
    abstract then this would imply a deep fetch (i.e., of sub-entity
    instances). If however the parent is not abstract then (even for
    horizontal inheritance) instances of the parent are fetched
    (resolving attributes appropriately from children for horizontal).

    with regards,
    --

    Lachlan Deck
  • Andrus Adamchik at May 30, 2007 at 9:00 am
    On May 30, 2007, at 7:27 AM, Lachlan Deck wrote:
    * Changes to the validation rules to allow ObjEntity with no db
    entity for abstract entities
    The question of 'isAbstract' is merely a question of 'can instances
    of this entity be instantiated'?

    Certainly changes to validation rules are necessary. But it is
    possible for an entity to be both abstract whilst having an
    associated db entity (e.g., vertical inheritance where the
    developer doesn't desire to instantiate instances of parent entity).
    Right. I guess ObjEntity without a DbEntity feature can be tucked
    onto one of the inheritance tasks.

    * maybe also some runtime checks for abstract entity (???)
    The only runtime checks I can foresee at the moment are:
    - a CayenneRuntimeException for attempting to do a fetch on an
    ObjEntity that has no associated db entity.

    Other logic will need to be in place that determines how deep the
    fetch is. e.g., if there's a SelectQuery on a parent entity that's
    abstract then this would imply a deep fetch (i.e., of sub-entity
    instances). If however the parent is not abstract then (even for
    horizontal inheritance) instances of the parent are fetched
    (resolving attributes appropriately from children for horizontal).
    This may also be a part of the inheritance discussion, but here is a
    one thing to note: SelectQuery (and other queries) supports
    "setResolvingInherited", which is a deep-fetch vs. no-deep-fetch flag.

    Andrus
  • Aristedes Maniatis at May 30, 2007 at 8:32 am

    On 29/05/2007, at 8:01 PM, Andrus Adamchik wrote:

    Trying to decompose it further (so that we could Jira individual
    chunks easily :-))... +1 for the abstract entities support, but
    they can also be implemented as a separate feature independent from
    inheritance per se.

    <obj-entity ...> needs the following additional (optional) xml
    attributes:
    - isAbstract="flag"
    +1

    Also the following steps will be needed:

    * Modeler checkbox for ObjEntity "abstract" flag Yes.
    * Changes to the code generation templates to generate abstract
    java classes for such entities
    Yes and the setIsAbstract() and getIsAbstract() functions for
    ObjEntity which go hand in hand.
    * Changes to the validation rules to allow ObjEntity with no db
    entity for abstract entities
    Actually I don't think that is needed for this first step. That is
    needed for step 2: horizontal inheritance.

    * maybe also some runtime checks for abstract entity (???)
    I think the main one is that you cannot perform a SelectQuery (or
    anything else that returns an ObjEntity) on an abstract entity with
    no concrete subclasses. Kind of makes isAbstract a bit useless on its
    own, but it is a step in the right direction.


    Ari





    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Kevin Menard at May 30, 2007 at 4:41 pm

    -----Original Message-----
    From: Aristedes Maniatis
    Sent: Wednesday, May 30, 2007 4:32 AM
    To: dev@cayenne.apache.org
    Subject: Re: Abstract Entities [Was: Modelling improvements:
    inheritance + interfacing (Draft)]
    * Changes to the code generation templates to generate
    abstract java
    classes for such entities
    Yes and the setIsAbstract() and getIsAbstract() functions for
    ObjEntity which go hand in hand.
    I'm clearly showing my ignorance on the matter here, but what does it
    mean for an object to know that it's abstract? Isn't that a property of
    the class? What happens when you subclass the ObjEntity?

    --
    Kevin
  • Mike Kienenberger at May 30, 2007 at 4:48 pm
    Hi Kevin,

    Let me guess the answer to this one.

    First we're talking about an ObjEntity, not a DataObject. So you'd
    never subclass it.

    As an example, one of my projects has WORK_ORDER, DISCONNECT_ORDER,
    CONNECT_ORDER (and so on) tables. WORK_ORDER is the common shared
    info by any kind of task. But you'd never have a WORK_ORDER entry
    without a subclass table. Thus, the template generator should never
    create WorkOrder as an abstract class. DisconnectOrder and
    ConnectOrder would inherit from that class and would not be abstract.

    On 5/30/07, Kevin Menard wrote:

    -----Original Message-----
    From: Aristedes Maniatis
    Sent: Wednesday, May 30, 2007 4:32 AM
    To: dev@cayenne.apache.org
    Subject: Re: Abstract Entities [Was: Modelling improvements:
    inheritance + interfacing (Draft)]
    * Changes to the code generation templates to generate
    abstract java
    classes for such entities
    Yes and the setIsAbstract() and getIsAbstract() functions for
    ObjEntity which go hand in hand.
    I'm clearly showing my ignorance on the matter here, but what does it
    mean for an object to know that it's abstract? Isn't that a property of
    the class? What happens when you subclass the ObjEntity?

    --
    Kevin
  • Kevin Menard at May 30, 2007 at 5:22 pm
    Gotcha. That makes a lot more sense now.

    Thanks,
    Kevin
    -----Original Message-----
    From: Mike Kienenberger
    Sent: Wednesday, May 30, 2007 12:47 PM
    To: dev@cayenne.apache.org
    Subject: Re: Abstract Entities [Was: Modelling improvements:
    inheritance + interfacing (Draft)]

    Hi Kevin,

    Let me guess the answer to this one.

    First we're talking about an ObjEntity, not a DataObject. So you'd
    never subclass it.

    As an example, one of my projects has WORK_ORDER,
    DISCONNECT_ORDER, CONNECT_ORDER (and so on) tables.
    WORK_ORDER is the common shared
    info by any kind of task. But you'd never have a WORK_ORDER entry
    without a subclass table. Thus, the template generator should never
    create WorkOrder as an abstract class. DisconnectOrder and
    ConnectOrder would inherit from that class and would not be abstract.
  • Mike Kienenberger at May 30, 2007 at 5:28 pm

    On 5/30/07, Mike Kienenberger wrote:
    info by any kind of task. But you'd never have a WORK_ORDER entry
    without a subclass table. Thus, the template generator should never
    create WorkOrder as an abstract class.
    Ugh. This should have been "would always create WorkOrder as an
    abstract class".
  • Aristedes Maniatis at May 31, 2007 at 12:32 am

    On 31/05/2007, at 2:40 AM, Kevin Menard wrote:

    I'm clearly showing my ignorance on the matter here, but what does it
    mean for an object to know that it's abstract? Isn't that a
    property of
    the class? What happens when you subclass the ObjEntity?
    Cayenne will need to know this information. For instance, you might
    have inheritance with an abstract superclass Person. Then performing
    a query on that class, Cayenne will need to automatically return
    objects of Student and Tutor subclasses and not the Person
    superclass. Effectively the flag "setResolvingInherited" will be
    switched on automatically.

    If nothing else, this information needs to be stored in the Datamap
    and the logical place is in the ObjEntity itself.

    When we get to vertical inheritance there will be at least one other
    property added to the ObjEntity: the name of the relationship used to
    find the superclass.

    Ari Maniatis



    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Mike Kienenberger at May 31, 2007 at 12:44 am

    On 5/30/07, Aristedes Maniatis wrote:
    When we get to vertical inheritance there will be at least one other
    property added to the ObjEntity: the name of the relationship used to
    find the superclass.
    When we get to inheritance, we'd be wise to follow the JPA methodology
    for specifying inheritance relationships. Vertical and single-table
    is well-defined. I can't remember if the optional horizontal
    relationships are spelled out in the spec.
  • Lachlan Deck at May 31, 2007 at 1:54 am

    On 31/05/2007, at 10:44 AM, Mike Kienenberger wrote:
    On 5/30/07, Aristedes Maniatis wrote:
    When we get to vertical inheritance there will be at least one other
    property added to the ObjEntity: the name of the relationship used to
    find the superclass.
    When we get to inheritance, we'd be wise to follow the JPA methodology
    for specifying inheritance relationships. Vertical and single-table
    is well-defined.
    Fair enough.

    <disclaimer>I'm coming from years in the land of EOF where for
    vertical inheritance there is indeed a relationship to the parent.
    But this was needed, I suppose, in order to flatten the parent's
    attributes/relationships into the child; but there's not much
    difference, conceptually, for mapping inheritance</disclaimer>

    So really (if that idea was switched for something more JPA friendly)
    the Inheritance strategy [as I mentioned in the original email
    'Modelling improvements: inheritance + interfacing (Draft)'] is still
    easy determined by these simple conditions:
    a) is the parent ObjEntity mapped to the same DbEntity?
    b) is the parent ObjEntity mapped to a DbEntity at all?

    e.g.,
    a == YES, b == YES --> Inheritance.SINGLE_TABLE
    a == NO, b == NO --> Inheritance.TABLE_PER_CLASS
    a == NO, b == YES --> Inheritance.JOINED

    ... and together with the further condition (isAbstract) also
    determines whether we're doing a deep fetch, plus whether there's an
    @DiscriminatorColumn etc.

    Okay, so consider the request for superRelationship dropped. (See
    disclaimer :-) Well that makes it simpler to do all of this ;-)
    I can't remember if the optional horizontal
    relationships are spelled out in the spec.
    from: http://java.sys-con.com/read/286901.htm
    - SINGLE_TABLE: Single-table-per-class inheritance hierarchy. This is
    the default strategy. The entity hierarchy is essentially flattened
    into the sum of its fields, and these fields are mapped down to a
    single table.
    - JOINED [1]: Common base table, with joined subclass tables. In this
    approach, each entity in the hierarchy maps to its own dedicated
    table that maps only the fields declared on that entity. The root
    entity in the hierarchy is known as the base table, and the tables
    for all other entities in the hierarchy join with the base table.
    - TABLE_PER_CLASS [2]: Single-table-per-outermost concrete entity
    class. This strategy maps each leaf (i.e., outermost, concrete)
    entity to its own dedicated table. Each such leaf entity branch is
    flattened, combining its declared fields with the declared fields on
    all of its super-entities, and the sum of these fields is mapped onto
    its table.

    [1] vertical inheritance
    [2] horizontal inheritance

    with regards,
    --

    Lachlan Deck
  • Lachlan Deck at May 31, 2007 at 2:24 am

    On 31/05/2007, at 11:54 AM, Lachlan Deck wrote:
    On 31/05/2007, at 10:44 AM, Mike Kienenberger wrote:
    On 5/30/07, Aristedes Maniatis wrote:
    When we get to vertical inheritance there will be at least one other
    property added to the ObjEntity: the name of the relationship
    used to
    find the superclass.
    When we get to inheritance, we'd be wise to follow the JPA
    methodology
    for specifying inheritance relationships. Vertical and single-table
    is well-defined.
    <...>
    Okay, so consider the request for superRelationship dropped. (See
    disclaimer :-) Well that makes it simpler to do all of this ;-)
    Hang on... Hibernate, for example, does indeed utilise a
    relationship, to my understanding [1], that specifies the nature of
    the relationship to the parent, what happens when an object is
    deleted and so on. These are characteristics that are encapsulated in
    a relationship. This is why the request for defining a
    superRelationship in ObjEntity was first made. Perhaps it's an
    optional for vertical where in its absence is some implicit strategy.

    Thoughts?

    with regards,
  • Craig L Russell at May 31, 2007 at 3:03 am

    On May 30, 2007, at 7:23 PM, Lachlan Deck wrote:
    On 31/05/2007, at 11:54 AM, Lachlan Deck wrote:
    On 31/05/2007, at 10:44 AM, Mike Kienenberger wrote:
    On 5/30/07, Aristedes Maniatis wrote:
    When we get to vertical inheritance there will be at least one
    other
    property added to the ObjEntity: the name of the relationship
    used to
    find the superclass.
    When we get to inheritance, we'd be wise to follow the JPA
    methodology
    for specifying inheritance relationships. Vertical and single-table
    is well-defined.
    <...>
    Okay, so consider the request for superRelationship dropped. (See
    disclaimer :-) Well that makes it simpler to do all of this ;-)
    Hang on... Hibernate, for example, does indeed utilise a
    relationship, to my understanding [1], that specifies the nature of
    the relationship to the parent, what happens when an object is
    deleted and so on. These are characteristics that are encapsulated
    in a relationship. This is why the request for defining a
    superRelationship in ObjEntity was first made. Perhaps it's an
    optional for vertical where in its absence is some implicit strategy.

    Thoughts?
    The example below shows in Hibernate how to remove the automatically
    generated relationship between Person and Employee due to the need to
    map the primary key association to inheritance.

    I'd even call this a deficiency in the tool, since there is a foreign
    key constraint defined on the primary key column of the employees
    table that refers to the primary key column of the persons table. The
    most natural mapping of this would be inheritance and should
    therefore be the default.

    While it might be possible theoretically to define a different column
    in the database to be used as the association column to join rows of
    a subclass and a superclass table, by far the most common and most
    understandable way to map inheritance is to simply assume that the
    primary key of both tables is the same and that the id field in the
    class contains the value to be used for both primary keys. The
    direction of the foreign key constraint should indicate which is the
    subclass.

    Craig
    with regards,
    --

    Lachlan Deck

    [1] http://www.warfrog.com/hibernatetutorial2/
    Craig Russell
    Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
    408 276-5638 mailto:Craig.Russell@sun.com
    P.S. A good JDO? O, Gasp!
  • Lachlan Deck at May 31, 2007 at 3:20 am
    Hi there,
    On 31/05/2007, at 1:03 PM, Craig L Russell wrote:
    On May 30, 2007, at 7:23 PM, Lachlan Deck wrote:
    On 31/05/2007, at 11:54 AM, Lachlan Deck wrote:
    On 31/05/2007, at 10:44 AM, Mike Kienenberger wrote:
    On 5/30/07, Aristedes Maniatis wrote:
    When we get to vertical inheritance there will be at least one
    other
    property added to the ObjEntity: the name of the relationship
    used to
    find the superclass.
    When we get to inheritance, we'd be wise to follow the JPA
    methodology
    for specifying inheritance relationships. Vertical and single-table
    is well-defined.
    <...>
    Okay, so consider the request for superRelationship dropped. (See
    disclaimer :-) Well that makes it simpler to do all of this ;-)
    Hang on... Hibernate, for example, does indeed utilise a
    relationship, to my understanding [1], that specifies the nature
    of the relationship to the parent, what happens when an object is
    deleted and so on. These are characteristics that are encapsulated
    in a relationship. This is why the request for defining a
    superRelationship in ObjEntity was first made. Perhaps it's an
    optional for vertical where in its absence is some implicit strategy.

    Thoughts?
    The example below shows in Hibernate how to remove the
    automatically generated relationship between Person and Employee
    due to the need to map the primary key association to inheritance.

    I'd even call this a deficiency in the tool, since there is a
    foreign key constraint defined on the primary key column of the
    employees table that refers to the primary key column of the
    persons table. The most natural mapping of this would be
    inheritance and should therefore be the default.

    While it might be possible theoretically to define a different
    column in the database to be used as the association column to join
    rows of a subclass and a superclass table, by far the most common
    and most understandable way to map inheritance is to simply assume
    that the primary key of both tables is the same and that the id
    field in the class contains the value to be used for both primary
    keys. The direction of the foreign key constraint should indicate
    which is the subclass.
    Sure. (talking from EOF experience again...) the EOF docs for
    vertical talked about the need for creating a relationship for the
    case where the tables already exist (and thus their names, for
    example, may differ) and you're wanting to introduce inheritance
    (though in practice it needed the relationship either way but that's
    irrelevant here).

    However, my question remains this: if not defined in a relationship
    where does the developer define the delete rules etc? Or are you
    suggesting they don't get an option?

    with regards,
    --

    Lachlan Deck
  • Craig L Russell at May 31, 2007 at 6:13 am
    Hi Lachlan,
    On May 30, 2007, at 8:19 PM, Lachlan Deck wrote:

    Hi there,
    On 31/05/2007, at 1:03 PM, Craig L Russell wrote:
    On May 30, 2007, at 7:23 PM, Lachlan Deck wrote:
    On 31/05/2007, at 11:54 AM, Lachlan Deck wrote:
    On 31/05/2007, at 10:44 AM, Mike Kienenberger wrote:
    On 5/30/07, Aristedes Maniatis wrote:
    When we get to vertical inheritance there will be at least one
    other
    property added to the ObjEntity: the name of the relationship
    used to
    find the superclass.
    When we get to inheritance, we'd be wise to follow the JPA
    methodology
    for specifying inheritance relationships. Vertical and single-
    table
    is well-defined.
    <...>
    Okay, so consider the request for superRelationship dropped.
    (See disclaimer :-) Well that makes it simpler to do all of
    this ;-)
    Hang on... Hibernate, for example, does indeed utilise a
    relationship, to my understanding [1], that specifies the nature
    of the relationship to the parent, what happens when an object is
    deleted and so on. These are characteristics that are
    encapsulated in a relationship. This is why the request for
    defining a superRelationship in ObjEntity was first made. Perhaps
    it's an optional for vertical where in its absence is some
    implicit strategy.

    Thoughts?
    The example below shows in Hibernate how to remove the
    automatically generated relationship between Person and Employee
    due to the need to map the primary key association to inheritance.

    I'd even call this a deficiency in the tool, since there is a
    foreign key constraint defined on the primary key column of the
    employees table that refers to the primary key column of the
    persons table. The most natural mapping of this would be
    inheritance and should therefore be the default.

    While it might be possible theoretically to define a different
    column in the database to be used as the association column to
    join rows of a subclass and a superclass table, by far the most
    common and most understandable way to map inheritance is to simply
    assume that the primary key of both tables is the same and that
    the id field in the class contains the value to be used for both
    primary keys. The direction of the foreign key constraint should
    indicate which is the subclass.
    Sure. (talking from EOF experience again...) the EOF docs for
    vertical talked about the need for creating a relationship for the
    case where the tables already exist (and thus their names, for
    example, may differ) and you're wanting to introduce inheritance
    (though in practice it needed the relationship either way but
    that's irrelevant here).
    Well, from the database perspective there is a difference based on
    the direction of the foreign key. In general, a subclass table
    contains the foreign key constraint. There might be several subclass
    tables, all of which have foreign key constraints on the primary key
    column of the superclass table.

    The specific case where there is always a row in each of the tables
    simply means that there are no other subclasses involved. And in
    fact, many ORM solutions offer a special case mapping for this, that
    doesn't involve relationships at all.
    However, my question remains this: if not defined in a relationship
    where does the developer define the delete rules etc? Or are you
    suggesting they don't get an option?
    In an inheritance situation, there is only one instance corresponding
    to the rows (one row in each table in the hierarchy). I'm suggesting
    that there is no option. If the instance is deleted, then the row in
    each table is deleted.

    Craig
    with regards,
    --

    Lachlan Deck

    Craig Russell
    Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
    408 276-5638 mailto:Craig.Russell@sun.com
    P.S. A good JDO? O, Gasp!
  • Lachlan Deck at May 31, 2007 at 6:19 am
    Hi Craig,
    On 31/05/2007, at 4:13 PM, Craig L Russell wrote:
    On May 30, 2007, at 8:19 PM, Lachlan Deck wrote:

    However, my question remains this: if not defined in a
    relationship where does the developer define the delete rules etc?
    Or are you suggesting they don't get an option?
    In an inheritance situation, there is only one instance
    corresponding to the rows (one row in each table in the hierarchy).
    I'm suggesting that there is no option. If the instance is deleted,
    then the row in each table is deleted.
    That's fine when the parent is abstract (i.e., not instantiatable).
    What about when the parent is not abstract and where it is thus
    possible to simply fetch/instantiate the parent entity on its own.
    What happens when the user deletes the parent object in such a
    situation? Should I not get the choice?

    with regards,
    --

    Lachlan Deck
  • Craig L Russell at May 31, 2007 at 6:32 am
    Hi Lachlan,
    On May 30, 2007, at 11:19 PM, Lachlan Deck wrote:

    Hi Craig,
    On 31/05/2007, at 4:13 PM, Craig L Russell wrote:
    On May 30, 2007, at 8:19 PM, Lachlan Deck wrote:

    However, my question remains this: if not defined in a
    relationship where does the developer define the delete rules
    etc? Or are you suggesting they don't get an option?
    In an inheritance situation, there is only one instance
    corresponding to the rows (one row in each table in the
    hierarchy). I'm suggesting that there is no option. If the
    instance is deleted, then the row in each table is deleted.
    That's fine when the parent is abstract (i.e., not instantiatable).
    What about when the parent is not abstract and where it is thus
    possible to simply fetch/instantiate the parent entity on its own.
    What happens when the user deletes the parent object in such a
    situation? Should I not get the choice?
    I don't believe that you should be able to fetch the parent entity on
    its own. IMHO If you allow the parent entity to be fetched and don't
    also fetch the data from the subclass then you have a broken mapping.
    The user should not be allowed to get a partial instance (data from
    the parent table only) because then the whole Java concept of
    subclasses overriding behavior doesn't work any more.

    Craig
    with regards,
    --

    Lachlan Deck

    Craig Russell
    Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
    408 276-5638 mailto:Craig.Russell@sun.com
    P.S. A good JDO? O, Gasp!
  • Lachlan Deck at May 31, 2007 at 6:51 am
    Hi again,
    On 31/05/2007, at 4:32 PM, Craig L Russell wrote:
    On May 30, 2007, at 11:19 PM, Lachlan Deck wrote:
    On 31/05/2007, at 4:13 PM, Craig L Russell wrote:
    On May 30, 2007, at 8:19 PM, Lachlan Deck wrote:

    However, my question remains this: if not defined in a
    relationship where does the developer define the delete rules
    etc? Or are you suggesting they don't get an option?
    In an inheritance situation, there is only one instance
    corresponding to the rows (one row in each table in the
    hierarchy). I'm suggesting that there is no option. If the
    instance is deleted, then the row in each table is deleted.
    That's fine when the parent is abstract (i.e., not
    instantiatable). What about when the parent is not abstract and
    where it is thus possible to simply fetch/instantiate the parent
    entity on its own. What happens when the user deletes the parent
    object in such a situation? Should I not get the choice?
    I don't believe that you should be able to fetch the parent entity
    on its own. IMHO If you allow the parent entity to be fetched and
    don't also fetch the data from the subclass then you have a broken
    mapping. The user should not be allowed to get a partial instance
    (data from the parent table only) because then the whole Java
    concept of subclasses overriding behavior doesn't work any more.
    There are numerous uses for these partial instances (if you'd like to
    call them that) when you want to only fetch the characteristics of
    the parent, for example, without also having to fault in the data for
    the subclasses. e.g., if I have a service thread that once every 10
    minutes or so polls a message-queue to send a message to a list of
    recipients the only data I'm interested in fetching in is that of the
    parent entity.

    This is not breaking any inheritance rules even in Java as I see it.
    It is after all possible in Java itself to have a non-abstract
    superclass. Whether this leads to a broken mapping or otherwise I
    don't believe should be a restriction enforced by the tool... but
    certainly you might like to document the advantages/disadvantages of
    such an approach.

    If it's of any help these concepts have been around for a while
    (http://developer.apple.com/documentation/WebObjects/UsingEOModeler/
    index.html).

    with regards,
    --

    Lachlan Deck
  • Andrus Adamchik at Jun 1, 2007 at 9:43 am

    On May 31, 2007, at 9:51 AM, Lachlan Deck wrote:

    There are numerous uses for these partial instances (if you'd like
    to call them that) when you want to only fetch the characteristics
    of the parent, for example, without also having to fault in the
    data for the subclasses. e.g., if I have a service thread that once
    every 10 minutes or so polls a message-queue to send a message to a
    list of recipients the only data I'm interested in fetching in is
    that of the parent entity.

    This is not breaking any inheritance rules even in Java as I see
    it. It is after all possible in Java itself to have a non-abstract
    superclass. Whether this leads to a broken mapping or otherwise I
    don't believe should be a restriction enforced by the tool... but
    certainly you might like to document the advantages/disadvantages
    of such an approach.
    Hmm... Thinking about it from different angles, I tend to agree with
    Lachlan. A user can bend the rules with a shallow fetch on a non-
    abstract superclass, as long as (s)he understands that this (a)
    breaks uniquing and (b) deleting or inserting such records is asking
    for trouble.

    Still IMO, this is not related to the delete rule discussion. An
    implied CASCADE is the right thing.

    Andrus
  • Craig L Russell at Jun 1, 2007 at 12:51 pm
    On Jun 1, 2007, at 2:42 AM, Andrus Adamchik wrote:
    On May 31, 2007, at 9:51 AM, Lachlan Deck wrote:

    There are numerous uses for these partial instances (if you'd like
    to call them that) when you want to only fetch the characteristics
    of the parent, for example, without also having to fault in the
    data for the subclasses. e.g., if I have a service thread that
    once every 10 minutes or so polls a message-queue to send a
    message to a list of recipients the only data I'm interested in
    fetching in is that of the parent entity.
    I still have trouble with this. If this is a requirement, I'd suggest
    mapping the superclass independently, that is using a completely
    different class. Then you can have part of your application that
    doesn't care about the subclass part at all.

    It would still be a very bad choice if you were to mix the model
    containing the full inheritance relationship and the partial mapping,
    because you would potentially have conflicting updates of the same
    data. But you would be avoiding the complexity and the usability
    issues associated with having an instance that was mapped as a
    subclass yet in memory had no subclass behavior.

    Craig
    This is not breaking any inheritance rules even in Java as I see
    it. It is after all possible in Java itself to have a non-abstract
    superclass. Whether this leads to a broken mapping or otherwise I
    don't believe should be a restriction enforced by the tool... but
    certainly you might like to document the advantages/disadvantages
    of such an approach.
    Hmm... Thinking about it from different angles, I tend to agree
    with Lachlan. A user can bend the rules with a shallow fetch on a
    non-abstract superclass, as long as (s)he understands that this (a)
    breaks uniquing and (b) deleting or inserting such records is
    asking for trouble.

    Still IMO, this is not related to the delete rule discussion. An
    implied CASCADE is the right thing.

    Andrus
    Craig Russell
    Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
    408 276-5638 mailto:Craig.Russell@sun.com
    P.S. A good JDO? O, Gasp!
  • Lachlan Deck at Jun 1, 2007 at 1:54 pm
    Hi there,
    On 01/06/2007, at 10:50 PM, Craig L Russell wrote:
    On Jun 1, 2007, at 2:42 AM, Andrus Adamchik wrote:
    On May 31, 2007, at 9:51 AM, Lachlan Deck wrote:

    There are numerous uses for these partial instances (if you'd
    like to call them that) when you want to only fetch the
    characteristics of the parent, for example, without also having
    to fault in the data for the subclasses. e.g., if I have a
    service thread that once every 10 minutes or so polls a message-
    queue to send a message to a list of recipients the only data I'm
    interested in fetching in is that of the parent entity.
    I still have trouble with this. If this is a requirement, I'd
    suggest mapping the superclass independently, that is using a
    completely different class.
    The question in the end is whether the tool/framework enforces what
    in the end (as it seems to me) comes down to an object design
    decision of which there are always various forks in the road as it
    can depend on the needs of the individual application (which we all
    know in reality can change/grow at any particular point in time
    throughout the life of an application). e.g., such design decisions
    cannot always be imposed upon legacy systems.

    I'm simply suggesting that Cayenne (and any other ORM for that
    matter) can quite simply allow for either case. To do so is at the
    end-user's risk.
    Then you can have part of your application that doesn't care about
    the subclass part at all.
    That certainly is a risk that is worth documenting for an end-
    developer but I don't believe should be enforced by the framework. In
    most situations (that I can envisage anyway) the use-case for
    instantiating a parent entity (rather than the sub-entity to which it
    belongs) would be in a read-only mode. But again that's application
    specific.
    It would still be a very bad choice if you were to mix the model
    containing the full inheritance relationship and the partial
    mapping, because you would potentially have conflicting updates of
    the same data.
    I'm not sure how that would be different from current update
    conflicts. Perhaps that would depend upon the locking behaviour
    (optimistic etc).
    But you would be avoiding the complexity and the usability issues
    associated with having an instance that was mapped as a subclass
    yet in memory had no subclass behavior.
    Are there any particular complexities you have in mind?

    For mine, any such complexity would be introduced by an individual
    developer, I believe, in edge-cases where for some strange reason the
    developer decides to modify the parent record (e.g., incrementing
    some dateOfLastAccess field).

    I suppose I keep coming back to this question: 'why should the
    framework impose an ideal restriction when there are in reality
    business cases for doing otherwise?' i.e., If allowing the parent
    record to be fetched on its own without needing to additionally fetch
    the sub-type characteristics allows for certain performance benefits,
    for example, or otherwise then for mine: +1. Some other developer may
    have some other needs for which these flexibilities finds a home. All
    in all my persuasion is that best-practices (for hazy areas like
    this) are best aimed at documentatation/white-papers.

    The only complexity I can envision (at this stage - perhaps Andrus
    would have a better idea) is dealing with the global ids for two
    objects in memory that for all intents and purpose are the same
    object, each of which are in separate contexts but where one was
    fetched as the superclass rather than the subclass it was originally
    created as. But other than that the normal rules would apply - i.e.,
    where the mapped entity that the parent object corresponds to is the
    parent entity that just happens to also have a sub-entity. I'm not
    certain at this stage how the object graph would track these. But it
    doesn't seem to be something that's conceptually difficult.
    This is not breaking any inheritance rules even in Java as I see
    it. It is after all possible in Java itself to have a non-
    abstract superclass. Whether this leads to a broken mapping or
    otherwise I don't believe should be a restriction enforced by the
    tool... but certainly you might like to document the advantages/
    disadvantages of such an approach.
    Hmm... Thinking about it from different angles, I tend to agree
    with Lachlan. A user can bend the rules with a shallow fetch on a
    non-abstract superclass, as long as (s)he understands that this
    (a) breaks uniquing and (b) deleting or inserting such records is
    asking for trouble.

    Still IMO, this is not related to the delete rule discussion. An
    implied CASCADE is the right thing.

    Andrus
    with regards,
    --

    Lachlan Deck
  • Aristedes Maniatis at May 31, 2007 at 5:09 am

    On 31/05/2007, at 1:03 PM, Craig L Russell wrote:

    While it might be possible theoretically to define a different
    column in the database to be used as the association column to join
    rows of a subclass and a superclass table, by far the most common
    and most understandable way to map inheritance is to simply assume
    that the primary key of both tables is the same and that the id
    field in the class contains the value to be used for both primary
    keys. The direction of the foreign key constraint should indicate
    which is the subclass.
    Yes, 99% of the time this is correct. However, if we want to support
    compound primary keys there is a need to describe how the columns in
    the subclass map to the columns in the superclass. That way Cayenne
    can populate them both correctly. Our original plan was to use an
    object relationship description in the DataMap to describe this
    pairing. The alternative is to use the names of the object attributes
    in order to match the primary key columns to each other, but
    something about this bothers me as an approach.

    Also, as Lachlan points out, this means that we don't get to specific
    nullify, cascade, etc delete rules. If you have a concrete
    superclass, you may wish to nullify the relationship when deleting
    the subclass record. Naturally if the superclass is abstract this is
    not allowed. But specifying the objrelationship explicitly allows us
    to put these rules somewhere and remove any ambiguity from compound
    key relationships.

    Ari



    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Srinivas sagar at May 31, 2007 at 5:45 am
    I have tried to unsubscribe from this list by sending
    an email to unsubscribe@cayenne.apache.org , but to no
    avail can anybody suggest how else I could try ?




    ____________________________________________________________________________________Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out.
    http://answers.yahoo.com/dir/?link=list&sid=396545469
  • Lachlan Deck at May 31, 2007 at 5:47 am

    On 31/05/2007, at 3:44 PM, srinivas sagar wrote:

    I have tried to unsubscribe from this list by sending
    an email to unsubscribe@cayenne.apache.org , but to no
    avail can anybody suggest how else I could try ?
    How about reading here:
    http://cayenne.apache.org/mailing-lists.html

    with regards,
    --

    Lachlan Deck
  • Aristedes Maniatis at May 31, 2007 at 5:48 am

    On 31/05/2007, at 3:44 PM, srinivas sagar wrote:

    I have tried to unsubscribe from this list by sending
    an email to unsubscribe@cayenne.apache.org , but to no
    avail can anybody suggest how else I could try ?

    http://cayenne.apache.org/mailing-lists.html


    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Andrus Adamchik at Jun 1, 2007 at 9:03 am
    Hi,

    Per http://cayenne.apache.org/mailing-lists.html the right email
    address is "dev-unsubscribe@cayenne.apache.org". Let me know if this
    still didn't work, and I'll unsubscribe you manually.

    Andrus
    On May 31, 2007, at 8:44 AM, srinivas sagar wrote:

    I have tried to unsubscribe from this list by sending
    an email to unsubscribe@cayenne.apache.org , but to no
    avail can anybody suggest how else I could try ?
  • Craig L Russell at May 31, 2007 at 6:59 am
    Hi Aristedes,
    On May 30, 2007, at 10:09 PM, Aristedes Maniatis wrote:

    On 31/05/2007, at 1:03 PM, Craig L Russell wrote:

    While it might be possible theoretically to define a different
    column in the database to be used as the association column to
    join rows of a subclass and a superclass table, by far the most
    common and most understandable way to map inheritance is to simply
    assume that the primary key of both tables is the same and that
    the id field in the class contains the value to be used for both
    primary keys. The direction of the foreign key constraint should
    indicate which is the subclass.
    Yes, 99% of the time this is correct. However, if we want to
    support compound primary keys there is a need to describe how the
    columns in the subclass map to the columns in the superclass.
    If it really is an inheritance relationship and not a one-one or one-
    many relationship, the compound primary keys should also correspond
    exactly.
    That way Cayenne can populate them both correctly. Our original
    plan was to use an object relationship description in the DataMap
    to describe this pairing. The alternative is to use the names of
    the object attributes in order to match the primary key columns to
    each other, but something about this bothers me as an approach.
    The most common case I've seen has a foreign key constraint defined
    on the primary key columns of the subclass table to the corresponding
    primary key columns of the superclass table.
    Also, as Lachlan points out, this means that we don't get to
    specific nullify, cascade, etc delete rules. If you have a concrete
    superclass, you may wish to nullify the relationship when deleting
    the subclass record. Naturally if the superclass is abstract this
    is not allowed. But specifying the objrelationship explicitly
    allows us to put these rules somewhere and remove any ambiguity
    from compound key relationships.
    This seems like an implementation detail (which I am very obviously
    not competent to comment on).

    Regards,

    Craig
    Ari



    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
    Craig Russell
    Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
    408 276-5638 mailto:Craig.Russell@sun.com
    P.S. A good JDO? O, Gasp!
  • Aristedes Maniatis at May 31, 2007 at 7:21 am

    On 31/05/2007, at 4:59 PM, Craig L Russell wrote:

    If it really is an inheritance relationship and not a one-one or
    one-many relationship, the compound primary keys should also
    correspond exactly.
    Then you are suggesting that we use the name of the attribute in the
    two ObjEntities as the mechanism to see which pairs correspond. My
    point is only that the names should not be special, particularly when
    a user might be refactoring an existing database scheme. Say the user
    has:

    Student.studentKey and Tutor.tutorKey as the PK attributes for their
    existing project. (Not the way I'd do it, but...)

    Now they want to add Person as a superclass. You are saying this
    should not be allowed without renaming the existing attributes?

    Also, as Lachlan points out, this means that we don't get to
    specific nullify, cascade, etc delete rules. If you have a
    concrete superclass, you may wish to nullify the relationship when
    deleting the subclass record. Naturally if the superclass is
    abstract this is not allowed. But specifying the objrelationship
    explicitly allows us to put these rules somewhere and remove any
    ambiguity from compound key relationships.
    This seems like an implementation detail (which I am very obviously
    not competent to comment on).
    Well, it is a functionality decision. Do we want users to be able to
    delete the subclass without deleting the superclass? If the
    superclass is concrete why not allow that to happen? And in that
    case, we need to store the relationship attributes somewhere.
    Thankfully, we already have a mechanism to do this.

    I'm not 100% clear on what you are proposing. Is it that Cayenne
    should be able to construct the appropriate JOIN by looking just at
    the PK flag s on the attributes in question, without needing any
    other information stored in XML in the model? If so, why is that
    better than storing the (possibly redundant, but not always)
    information in the XML datamap file?


    Ari Maniatis


    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Craig L Russell at May 31, 2007 at 6:47 pm
    Hi Ari,
    On May 31, 2007, at 12:21 AM, Aristedes Maniatis wrote:
    On 31/05/2007, at 4:59 PM, Craig L Russell wrote:

    If it really is an inheritance relationship and not a one-one or
    one-many relationship, the compound primary keys should also
    correspond exactly.
    Then you are suggesting that we use the name of the attribute in
    the two ObjEntities as the mechanism to see which pairs correspond.
    No, I'm suggesting to look at the database schema to find the cases
    of foreign key == primary key.

    And I don't think there is any need for two different fields to
    represent the columns in the database that because of foreign key
    constraints will always contain identical values.
    My point is only that the names should not be special, particularly
    when a user might be refactoring an existing database scheme. Say
    the user has:

    Student.studentKey and Tutor.tutorKey as the PK attributes for
    their existing project. (Not the way I'd do it, but...)

    Now they want to add Person as a superclass. You are saying this
    should not be allowed without renaming the existing attributes?
    I'm a bit unclear what this scenario means. If they want to add
    Person as a superclass, I would say they need to remap the classes so
    that the field in the superclass Person corresponding to the primary
    key columns is the identity field and there is no longer any identity
    field in the subclasses.
    Also, as Lachlan points out, this means that we don't get to
    specific nullify, cascade, etc delete rules. If you have a
    concrete superclass, you may wish to nullify the relationship
    when deleting the subclass record. Naturally if the superclass is
    abstract this is not allowed. But specifying the objrelationship
    explicitly allows us to put these rules somewhere and remove any
    ambiguity from compound key relationships.
    This seems like an implementation detail (which I am very
    obviously not competent to comment on).
    Well, it is a functionality decision. Do we want users to be able
    to delete the subclass without deleting the superclass?
    If this is a requirement, I'd recommend against mapping this schema
    as inheritance. I'd map it as a one-to-zero-or-one relationship. Then
    it's easy to delete the "subclass" instance while leaving the
    "superclass" instance intact.
    If the superclass is concrete why not allow that to happen? And in
    that case, we need to store the relationship attributes somewhere.
    Thankfully, we already have a mechanism to do this.

    I'm not 100% clear on what you are proposing. Is it that Cayenne
    should be able to construct the appropriate JOIN by looking just at
    the PK flag s on the attributes in question, without needing any
    other information stored in XML in the model? If so, why is that
    better than storing the (possibly redundant, but not always)
    information in the XML datamap file?
    I'm suggesting that the tool that generates the Java model from the
    database schema should be configurable to recognize the specific
    pattern of table2 having a primary key == foreign key to table1 and
    generate an inheritance relationship of class2 extends class1. If the
    requirement is to be able to independently manage instances of class1
    and class2, then the tool should be able to map this pattern as a one-
    to-zero-or-one relationship.

    And just so it's clear, I'm not an expert in Cayenne [or EOF]. I'm
    only offering suggestions based on a few years of doing enterprise
    ORM. And the closer you are to being concept-compliant with JPA and
    JDO, the more your users will be able to use other standards.
    Reusable programmers is still a viable objective.

    Craig

    Ari Maniatis


    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
    Craig Russell
    Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
    408 276-5638 mailto:Craig.Russell@sun.com
    P.S. A good JDO? O, Gasp!
  • Aristedes Maniatis at Jun 1, 2007 at 12:06 am

    On 31/05/2007, at 11:46 PM, Craig L Russell wrote:

    Hi Ari,
    On May 31, 2007, at 12:21 AM, Aristedes Maniatis wrote:

    Then you are suggesting that we use the name of the attribute in
    the two ObjEntities as the mechanism to see which pairs correspond.
    No, I'm suggesting to look at the database schema to find the cases
    of foreign key == primary key.

    And I don't think there is any need for two different fields to
    represent the columns in the database that because of foreign key
    constraints will always contain identical values.
    Well, normally the primary key attributes are not exposed in the
    ObjEntity anyway, so I agree with what I think you are saying. But
    the question here is about compound primary keys. If we want to be
    able to support them as the basis for the join in vertical
    inheritance, then we need an objRelationship explicitly defined.


    Well, it is a functionality decision. Do we want users to be able
    to delete the subclass without deleting the superclass?
    If this is a requirement, I'd recommend against mapping this schema
    as inheritance. I'd map it as a one-to-zero-or-one relationship.
    Then it's easy to delete the "subclass" instance while leaving the
    "superclass" instance intact.
    Sure, that might be the way you would want to do it, but why do we
    want to limit what others might want to do? As an example, we have in
    our current project two tables:

    BinaryInfo
    BinaryData

    The info table contains metadata (creator, date, size, etc) and the
    data table contains just the blob (pdf, image, etc). We wanted this
    structure in separate tables so that:

    * we could have different backup strategies for each
    * we could optimise one table for big unindexed data
    * we could put one table on a different db server, or whatever

    At the moment, this is a one-one relationship, but inheritance would
    be been much nicer. We would want both classes to be concrete so that
    we could fetch binaryInfo over the network (say to display a list of
    attachments) without fetching the BLOBs. We'd also like the ability
    to 'delete' records by removing the binaryData completely and leaving
    the binaryInfo record behind with a isDeleted flag for historical
    auditing.
    If the superclass is concrete why not allow that to happen? And in
    that case, we need to store the relationship attributes somewhere.
    Thankfully, we already have a mechanism to do this.

    I'm not 100% clear on what you are proposing. Is it that Cayenne
    should be able to construct the appropriate JOIN by looking just
    at the PK flag s on the attributes in question, without needing
    any other information stored in XML in the model? If so, why is
    that better than storing the (possibly redundant, but not always)
    information in the XML datamap file?
    I'm suggesting that the tool that generates the Java model from the
    database schema should be configurable to recognize the specific
    pattern of table2 having a primary key == foreign key to table1 and
    generate an inheritance relationship of class2 extends class1. If
    the requirement is to be able to independently manage instances of
    class1 and class2, then the tool should be able to map this pattern
    as a one-to-zero-or-one relationship.
    Sure. Although I haven't been thinking of it from a reverse
    engineering perspective at all. That would be a useful extension.
    And just so it's clear, I'm not an expert in Cayenne [or EOF]. I'm
    only offering suggestions based on a few years of doing enterprise
    ORM.
    And Cayenne's implementation will be all the better for the extra
    thinking your suggestions provoke.

    And the closer you are to being concept-compliant with JPA and JDO,
    the more your users will be able to use other standards. Reusable
    programmers is still a viable objective.
    I agree. But at the same time, just because JPA/JDO people put a
    limitation in the specification doesn't been we have to draw the line
    there. We can always implement more functionality than is needed by
    those specs. If JPA says that the superclass is always abstract and
    we want to allow to make it concrete as an option, then more power to
    our users.


    Ari Maniatis




    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Andrus Adamchik at Jun 1, 2007 at 9:40 am
    This was a long thread, and I may have missed some points already
    made. Let me try to summarize this discussion and add my comments to
    it. There are two aspects of the "vertical inheritance relationship":

    1. Specifying the join semantics for non-trivial PK-to-PK mapping
    (such as compound keys).
    2. Specifying delete rules.

    I am with Ari on (1) - it is in the Cayenne philosophy to map things
    explicitly, so that various weird legacy schemas can still be mapped.
    I am with Craig on (2) - if a user expects to delete a record from a
    subclass table without deleting a record in a superclass table, this
    situation should not be mapped as inheritance, as it breaks the ORM
    model at a fundamental level (an object is deleted, but some of its
    properties still remain persistent - BAD).

    With this in mind we do not need an inheritance ObjRelationship, but
    we may use a DbRelationship to store join semantics (anybody
    mentioned that already??). Another nice side effect of it is that
    such relationship is not a part of the object model (ObjRelationship
    would've been an object property). So there is nothing artificial
    about such mapping, and no new concepts are needed in Cayenne to map it.

    Andrus
  • Lachlan Deck at Jun 1, 2007 at 12:28 pm

    On 01/06/2007, at 7:32 PM, Andrus Adamchik wrote:

    With this in mind we do not need an inheritance ObjRelationship,
    but we may use a DbRelationship to store join semantics (anybody
    mentioned that already??).
    Well the original suggestion I made was for <obj-entity
    superRelationship="nameOfRelationship" ...> to allow for specifically
    specifying vertical inheritance (which would have the effect of not
    listing this relationship along with those returned from
    objEntity.getRelationships() but via objEntity.getSuperRelationship().

    Are you suggesting that you'd prefer <db-entity
    superRelationship="nameOfRelationship" ...> or just figuring out the
    relationship by finding the one that happens to map to the parent as
    a toOne?

    The nice thing I thought about having a superRelationship definition
    in the modeler is that you can then make your inheritance choice in
    one place and it's clear of the choice. i.e., the above would just
    require an additional popup next to the popup for which DbEntity an
    ObjEntity maps to to choose a relationship. Otherwise perhaps it
    wouldn't be as clear whether such a relationship exists.

    The other option I considered initially was having superRelationship
    as a boolean flag with validation to ensure there was an accompanying
    relationship called 'super' but thought this unnecessarily
    restrictive in the end.
    Another nice side effect of it is that such relationship is not a
    part of the object model (ObjRelationship would've been an object
    property). So there is nothing artificial about such mapping, and
    no new concepts are needed in Cayenne to map it.
    Can you clarify this a bit more.

    Thanks.

    with regards,
    --

    Lachlan Deck
  • Andrus Adamchik at Jun 3, 2007 at 9:12 am
    Hi Lachlan,
    On Jun 1, 2007, at 3:24 PM, Lachlan Deck wrote:
    On 01/06/2007, at 7:32 PM, Andrus Adamchik wrote:

    With this in mind we do not need an inheritance ObjRelationship,
    but we may use a DbRelationship to store join semantics (anybody
    mentioned that already??).
    Well the original suggestion I made was for <obj-entity
    superRelationship="nameOfRelationship" ...> to allow for
    specifically specifying vertical inheritance (which would have the
    effect of not listing this relationship along with those returned
    from objEntity.getRelationships() but via
    objEntity.getSuperRelationship().
    This is what I was trying to avoid - introducing relationships with
    special behavior.

    Are you suggesting that you'd prefer <db-entity
    superRelationship="nameOfRelationship" ...>
    No, as DbEntities (tables) do not have inheritance among themselves.
    It would be more of <obj-entity
    superDbRelationship="nameOfDBRelationship" ...>, but I do believe
    that this can be made implicit, as arguably there can be only one
    DbRelationship between the primary keys of two tables. E.g:

    SuperOE -> DB1
    SubOE1 -> DB2
    SubOE2 -> DB3

    In this case Cayenne can easily figure out the name of DB2->DB1 and
    DB3->DB1 relationships based on relationship semantics.
    Another nice side effect of it is that such relationship is not a
    part of the object model (ObjRelationship would've been an object
    property). So there is nothing artificial about such mapping, and
    no new concepts are needed in Cayenne to map it.
    Can you clarify this a bit more.
    See above - I don't want to redefine what ObjRelationship is. The
    difference between Cayenne and EOF is that Cayenne splits DB and Java
    mapping in two separate layers of metadata. EOF allows to mark a
    relationship as "not included in the object model", while Cayenne
    allows to map the DB relationship without mapping corresponding
    ObjRelationship, essentially achieving the same thing in a different
    way.

    Andrus
  • Lachlan Deck at Jun 3, 2007 at 8:01 pm
    Hi Andrus,
    On 03/06/2007, at 7:12 PM, Andrus Adamchik wrote:
    On Jun 1, 2007, at 3:24 PM, Lachlan Deck wrote:
    On 01/06/2007, at 7:32 PM, Andrus Adamchik wrote:

    With this in mind we do not need an inheritance ObjRelationship,
    but we may use a DbRelationship to store join semantics (anybody
    mentioned that already??).
    Well the original suggestion I made was for <obj-entity
    superRelationship="nameOfRelationship" ...> to allow for
    specifically specifying vertical inheritance (which would have the
    effect of not listing this relationship along with those returned
    from objEntity.getRelationships() but via
    objEntity.getSuperRelationship().
    This is what I was trying to avoid - introducing relationships with
    special behavior.
    Okay. It'd be perhaps less obvious what type of inheritance was in
    play in the modeller but then again perhaps a simple dynamic label
    could display something to the same effect along with the below
    validation.
    Are you suggesting that you'd prefer <db-entity
    superRelationship="nameOfRelationship" ...>
    No, as DbEntities (tables) do not have inheritance among
    themselves. It would be more of <obj-entity
    superDbRelationship="nameOfDBRelationship" ...>, but I do believe
    that this can be made implicit, as arguably there can be only one
    DbRelationship between the primary keys of two tables. E.g:

    SuperOE -> DB1
    SubOE1 -> DB2
    SubOE2 -> DB3

    In this case Cayenne can easily figure out the name of DB2->DB1 and
    DB3->DB1 relationships based on relationship semantics.
    Okay great. I suppose there'd need to be validation to that effect to
    ensure that such relations exist when choosing a different DbEntity
    from the parent entity.
    Another nice side effect of it is that such relationship is not a
    part of the object model (ObjRelationship would've been an object
    property). So there is nothing artificial about such mapping, and
    no new concepts are needed in Cayenne to map it.
    Can you clarify this a bit more.
    See above - I don't want to redefine what ObjRelationship is. The
    difference between Cayenne and EOF is that Cayenne splits DB and
    Java mapping in two separate layers of metadata. EOF allows to mark
    a relationship as "not included in the object model", while Cayenne
    allows to map the DB relationship without mapping corresponding
    ObjRelationship, essentially achieving the same thing in a
    different way.
    Thanks. Just a slight mind-shift ;-)

    with regards,
    --

    Lachlan Deck
  • Lachlan Deck at Jun 1, 2007 at 1:52 am
    Hi Craig,
    On 31/05/2007, at 11:46 PM, Craig L Russell wrote:
    On May 31, 2007, at 12:21 AM, Aristedes Maniatis wrote:
    On 31/05/2007, at 4:59 PM, Craig L Russell wrote:

    If it really is an inheritance relationship and not a one-one or
    one-many relationship, the compound primary keys should also
    correspond exactly.
    Then you are suggesting that we use the name of the attribute in
    the two ObjEntities as the mechanism to see which pairs correspond.
    No, I'm suggesting to look at the database schema to find the cases
    of foreign key == primary key.
    Good point. I think that's exactly what we've been suggesting (for
    vertical inheritance) except that such constraints are not
    necessarily always within the RDBMS but within the Cayenne model.
    And I don't think there is any need for two different fields to
    represent the columns in the database that because of foreign key
    constraints will always contain identical values.
    Perhaps that assumes that there are indeed such constraints in the
    database (which is not always the case). You'd naturally hope for
    that to be the case in normal circumstances but it's also possible to
    impose in-memory constraints within Cayenne, EOF, or (I assume) any
    other ORM system.
    My point is only that the names should not be special,
    particularly when a user might be refactoring an existing database
    scheme. Say the user has:
    Student.studentKey and Tutor.tutorKey as the PK attributes for
    their existing project. (Not the way I'd do it, but...)
    Now they want to add Person as a superclass. You are saying this
    should not be allowed without renaming the existing attributes?
    I'm a bit unclear what this scenario means. If they want to add
    Person as a superclass, I would say they need to remap the classes
    so that the field in the superclass Person corresponding to the
    primary key columns is the identity field and there is no longer
    any identity field in the subclasses.
    Ahh, I think I see where we're coming at this differently (maybe,
    correct me if I've misunderstood you :-). The only place where the
    primary/foreign keys are defined (or remapped) with Cayenne (or EOF
    for that matter) are within the model; not within the java classes as
    they are deemed database artefacts that the user is unaware of in
    normal circumstances. There is nothing in code (unless you choose to
    expose the primary/foreign key(s) as class attributes) that tells the
    programmer what the name of the primary key is. It's usually irrelevant.

    Thus the normal rules of inheritance-within-java is a different
    scenario where it is indeed impossible to change the signature of an
    inherited attribute/method. Here, there is no signature to change -
    they're only known to the Cayenne runtime as defined in the model.

    Within the modelling environment we're essentially creating "is-a"
    relationships. So the question being discussed here is how is that
    relationship defined? The answer to that question depends upon the
    type of inheritance chosen.

    For vertical (or Inheritance.JOINED), for example, at runtime I'm
    envisaging (based upon EOF experience) that Cayenne would propagate a
    primary key value from the super-class table to the subclass table
    when inserting a new record (seeing as the next primary key value is
    a function of the parent table [or some other table that's keeping
    tabs]).
    Also, as Lachlan points out, this means that we don't get to
    specific nullify, cascade, etc delete rules. If you have a
    concrete superclass, you may wish to nullify the relationship
    when deleting the subclass record. Naturally if the superclass
    is abstract this is not allowed. But specifying the
    objrelationship explicitly allows us to put these rules
    somewhere and remove any ambiguity from compound key relationships.
    This seems like an implementation detail (which I am very
    obviously not competent to comment on).
    Well, it is a functionality decision. Do we want users to be able
    to delete the subclass without deleting the superclass?
    If this is a requirement, I'd recommend against mapping this schema
    as inheritance. I'd map it as a one-to-zero-or-one relationship.
    Then it's easy to delete the "subclass" instance while leaving the
    "superclass" instance intact.
    Sure, something like a Role-based mapping might be a good choice or
    whatever. Here's a bad example of a situation where the parent record
    may not want to be deleted along with the sub-entity.

    Person -->> EmployeeRole
    ^

    is-a -- Client
    I'm suggesting that the tool that generates the Java model from the
    database schema should be configurable to recognize the specific
    pattern of table2 having a primary key == foreign key to table1 and
    generate an inheritance relationship of class2 extends class1.
    I suspect we might be coming at this from different angles. I'm
    coming from the angle of modelling your object hierarchy to a schema
    (whether it exists or not) vs the other way around.
    If the requirement is to be able to independently manage instances
    of class1 and class2, then the tool should be able to map this
    pattern as a one-to-zero-or-one relationship.
    By independently manage I assume you're talking about non-inheritance-
    based relationships which Cayenne fully supports ;-)
    And just so it's clear, I'm not an expert in Cayenne [or EOF]. I'm
    only offering suggestions based on a few years of doing enterprise
    ORM.
    Which is much appreciated. That's why this whole discussion began -
    so as to share ideas on this. I'm coming at this from an EOF heritage
    which has a certain mindset. Certainly Cayenne has its own (yet
    similar) approaches to these things and so such discussions are only
    helpful.
    And the closer you are to being concept-compliant with JPA and JDO,
    the more your users will be able to use other standards. Reusable
    programmers is still a viable objective.
    Indeed.

    with regards,
    --

    Lachlan Deck
  • Andrus Adamchik at Jun 1, 2007 at 9:55 am
    IMO, "abstract" is limited to its Java definition, and is of no
    consequence to the runtime inheritance processing (note that
    'resolvingInherited' query property is true by default). So the most
    important aspect of it is generating a corresponding Java class with
    an "abstract" keyword, so that Java could throw on any attempts to
    instantiate it.

    Andrus


    On May 31, 2007, at 3:32 AM, Aristedes Maniatis wrote:

    On 31/05/2007, at 2:40 AM, Kevin Menard wrote:

    I'm clearly showing my ignorance on the matter here, but what does it
    mean for an object to know that it's abstract? Isn't that a
    property of
    the class? What happens when you subclass the ObjEntity?
    Cayenne will need to know this information. For instance, you might
    have inheritance with an abstract superclass Person. Then
    performing a query on that class, Cayenne will need to
    automatically return objects of Student and Tutor subclasses and
    not the Person superclass. Effectively the flag
    "setResolvingInherited" will be switched on automatically.

    If nothing else, this information needs to be stored in the Datamap
    and the logical place is in the ObjEntity itself.

    When we get to vertical inheritance there will be at least one
    other property added to the ObjEntity: the name of the relationship
    used to find the superclass.

    Ari Maniatis



    -------------------------->
    Aristedes Maniatis
    phone +61 2 9660 9700
    PGP fingerprint 08 57 20 4B 80 69 59 E2 A9 BF 2D 48 C2 20 0C C8
  • Lachlan Deck at Jun 1, 2007 at 12:28 pm

    On 01/06/2007, at 6:55 PM, Andrus Adamchik wrote:

    IMO, "abstract" is limited to its Java definition, and is of no
    consequence to the runtime inheritance processing (note that
    'resolvingInherited' query property is true by default).
    I was thinking that 'isAbstract' (if true for the parent entity)
    might have the effect of implying that any attempt at setting
    'resolvingInherited' to false for a query would have no effect as it
    would be impossible to fulfil such a requirement in the query.
    Perhaps that's a more tolerant approach(?) than allowing the query to
    proceed but throwing an exception when attempting to instantiate the
    abstract parent. But then again I suppose this would train people
    quickly: 'don't do that!' ;-)
    So the most important aspect of it is generating a corresponding
    Java class with an "abstract" keyword, so that Java could throw on
    any attempts to instantiate it.
    Sure.

    with regards,
    --

    Lachlan Deck

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupdev @
categoriescayenne
postedMay 27, '07 at 7:11a
activeJun 3, '07 at 8:01p
posts54
users7
websitecayenne.apache.org

People

Translate

site design / logo © 2022 Grokbase