Hi
sorry to bother you again :-)
Our object model uses inheritance,
which is not supported by cayenne.
(Actually, it *is* supported in
the modeler and the mapping-DTD,
which can be confusing, because
modeling inheritance results in
runtime error about non-existing
relations)
I tried some changes to make
inheritance work, and that works,
as far as my tests are concerned.
From the discussion in the mailing
lists it seems that inheritance is
something you have in mind or are
working on, so I will not send you
any patches, but just discuss the
problems I encounterd.
- First problem is *who* decides from
the data-row which class to instanciate
for the data-object.
I put that as application code in the
data-object itself, by extending the
DataObject-interface by a method
"createNewInstance" (see attached file
"Person.java", with "Customer" and "Employee"
extending "Person")
Instrumenting the methods
objectFromDataRow/registeredObject
in DataContext to call "createNewInstance"
ensures that the correct type is instanciated
if a data-row is available.
- Second problem is how to deal with
"Hollow" objects where the type is not
known. There are basically 2 solutions:
- the type is part of the ObjectId,
so it is always known
- or hollow objects with inheritance
are instances of the base-class,
but never "published"
I used the second solution. That means
a mechanism in "CayenneDataObject"
to refetch a Hollow object when it
is read via "readProperty"
- Third problem is how to "inherit"
the attributes and relationships
accross the "ObjEntity"'s.
I used a mechanism to copy
(after loading the map)
the attributes and relations down
the inheritance hirachies, so
that every instance of ObjEntity
has at runtime it's full list of
attributes and relationships.
(This is of course a *BAD* solution,
because this means
to use at runtime a different
representation of inheritance then
in the model - an indeed this needs
another workaround to prevent
the modeler from doing that and
destroying the mapping-file....
But the "correct" solution of
following the inheritance at
runtime (when getAttributeList()
is called) is probably more
work to implement and more
processing at runtime)
- fourth problem is to make the
queries quering the "superset"
of all attributes for all possible
types.
I did that by adding in ObjEntity
the "superset" list of attributes
and a method "getAttributeSuperSetList()"
that I called from within "SelectTranslator"
instead of "getAttributeList()"
(same for relations)
This is all not really nice, but when
it comes to inheritance, one death you
have to die... (but anyway, it works)
Any comment on what what you think
about these problems/options/strategies
and if and when cayenne will support inheritance?
thanks,
Arndt
import java.util.Map;
import org.objectstyle.cayenne.DataObject;
public class Person extends _Person {
public static final int PERSON = 1;
public static final int EMPLOYEE = 2;
public static final int CUSTOMER = 3;
public Person() {
super();
setTyp( new Integer( PERSON ) );
}
public DataObject createNewInstance(Map map) {
// this is used to determine if this
// objects features inheritance
if ( map == null ) {
return this;
}
Integer iTyp = (Integer)map.get("TYP");
int typ = ( iTyp == null ? 0: iTyp.intValue() );
DataObject obj = null;
switch ( typ ) {
case PERSON : obj = new Person(); break;
case EMPLOYEE : obj = new Employee(); break;
case CUSTOMER : obj = new Customer(); break;
default : obj = null;
}
if ( obj != null ) {
copyInternalState( obj );
return obj;
} else {
return this;
}
}
}
This archive was generated by hypermail 2.0.0 : Sun Mar 02 2003 - 14:54:29 EST