Hi Marcin,
A few points adding to what Robert has already mentioned...
On Mar 27, 2008, at 4:33 PM, Marcin Skladaniec wrote:
"There are several object-relational mapping (ORM) java frameworks
in existence, and in my opinion Cayenne (http://cayenne.apache.org/)
is one of the best. Cayenne has clear and consistent API, and great,
most vibrant community I met in the open source world.
Cayenne has many features you one would expect ORM to have, but it
is lacking one important feature which is present in competing
projects like Hibernate: inheritance. I would like to propose a
Summer of Code project bringing inheritance to Cayenne.
Cayenne has single table inheritance fully working. So it is not
missing inheritance, just vertical and horizontal varieties of
inheritance mapping.
At the moment Cayenne does support only some sort of flat
inheritance (called 'derived entities' ), but it is already marked
as deprecated and will be excluded from future versions.
It is already dropped from 3.0
I believe (re)adding this feature is going to highly improve Cayenne
as ORM, I have already found myself missing it few times when
working on various database designs.
This may require some discussion. IIRC there was a thread on that in
the past, but I wouldn't call that inheritance, and for SoC I would
recommend to concentrate on *object* inheritance, which requirements
are well defined and well understood. BTW, here is a page that Ari
created that outlines the 3 varieties:
http://cayenne.apache.org/doc/inheritance-overview.html
Example: If an application has an entity representing different
payments each type of payment needs to be stored in separate table
and will be mapped to a separate entity, ie.
- CreditCardPayment[amount, bankedDate, ccNumber, ccExpiry, ...] <=>
CreditCardPayment<amount, bankedDate, ccNumber, ccExpiry, ...>
- ChequePayment[amount, dateBanked, chequeBank, ...] <=>
ChequePayment<amount, dateBanked, chequeBank, ...>
- CashPayment[amount, dateBanked, ...] <=> CashPayment<amount,
dateBanked, ...>
As can be seen some fields gets duplicated, and as there is no
inheritance between the java classes the application ends up with
plenty duplicate code. Also the relationships between the entities
might get complicated, for example an Invoice would need to have
separate relationship to each payment table.
Absolutely correct.
Flat inheritance
Let's call it "single table" to be consistent with the established
terminology.
Using flat inheritance has only limited usage, and if used to
extensively leads to tables with too many columns to be readable and
understandable.
The explanation is correct, but "limited usage" is an overstatement.
It is very useful and performs better than any other kind. So I guess
we shouldn't try to make a case that vertical/horizontal is better
than single table... It's just different, not better. All three have
their uses.
Example: In the same situation as before there would be only one
table defining all the fields :
- Payment[amount, bankedDate, ccNumber, ccExpiry,...,
chequeBank, ...] <=> CreditCardPayment<amount, bankedDate, ccNumber,
ccExpiry, ...>, ChequePayment<amount, dateBanked, chequeBank, ...>,
CashPayment<amount, dateBanked, ...>
Modelling the relationships becomes much easier, but as each entity
still is separate there is a high possibility of duplicate code.
Not true. There is a common superclass. Single table inheritance is a
real inheritance in a Java sense... Consider it a mapping technique
used to map a tree hierarchy of classes to a single table.
Horizontal inheritance can be considered a small improvement over
the no inheritance model, keeping the duplication of the fields on
the database and entity level, but allowing to gather some code
together. I'm finding this approach a little confusing and counter-
intuitive, but it certainly has a reason behind: it does avoid the
slowness related with vertical inheritance.
Example:
- (no database table) <=> Payment<amount, bankedDate, ...>
implements/extends CreditCardPayment, ChequePayment, CashPayment
- CreditCardPayment[ccNumber, ccExpiry, ...] <=>
CreditCardPayment<ccNumber, ccExpiry, ...>
- ChequePayment[chequeBank, ...] <=> ChequePayment<chequeBank, ...>
- CashPayment[...] <=> CashPayment<...>
Vertical inheritance escapes the problems of flat inheritance by
storing data relevant to an entity in a dedicated table. Resulting
database schema is cleaner and easier to maintain when adding new
entities and tables. There is a cost linked with this type of
inheritance: the database transaction speeds are lower, since each
fetching query must use a join and storing data has to be executed
against each table.
Example: Again the same situation as in previous cases. In vertical
inheritance there is a common table and common entity class finally
creating a room for the code common to all Payments:
- Payment[amount, bankedDate, ...] <=> Payment<amount,
bankedDate, ...>
- CreditCardPayment[ccNumber, ccExpiry, ...] <=>
CreditCardPayment<ccNumber, ccExpiry, ...> extends Payment
- ChequePayment[chequeBank, ...] <=> ChequePayment<chequeBank, ...>
extends Payment
- CashPayment[...] <=> CashPayment<...> extends Payment
My Google Summer of Code is going to bring the inheritance to
Cayenne. Certainly I would like to implement the vertical
inheritance, albeit it might have performance impact, it also seems
to be the most advanced model. If the time will allow I'll put my
effort to also implement either flat or horizontal inheritance,
consulting the Cayenne community to find which one is more
anticipated. "
Again, I disagree that single table is inferior... There are three
classic ways to map OO inheritance hierarchy to the relational model.
We have one, we need one or two more to give users more flexibility.
Finally, please don't take my comments as a negative reaction. I am
very happy that we have this proposal and looking forward to working
with you on implementing them.
Cheers,
Andrus