On 31/03/2009, at 10:26 PM, Joseph Schmidt wrote:

This would sound cool to me too, but from the Cayenne documentation example, this approach seems to have the problem that Java has single inheritance :(.

If there's only one such table than it would work (single inheritance). E.g. In the above example, by doing a superclass to point to the "tag" table(Tag entity), called "Taggable". All entities that would like to have "tag"s would just need to extend the "Taggable" entity.

The big problem is how to do it if there are more tables like that in the scheme :(.

Yes, you get to have exactly one Tag concept since you can have only one superclass. Otherwise you have to model this as an interface, but there is no support for that in Cayenne. You are on your own to implement that, which brings you to choice 2.

You could lobby Sun for multiple inheritance, but you might be waiting some time :-)


This a very common scenario for Web2.0 apps (at least for the schemes I've seen so far) :(.

Or has this something to do with "Horizontal Inheritance"?
https://issues.apache.org/jira/browse/CAY-795

Horizontal, vertical, single-table. These ideas are only about the database implementation and don't affect how the Java classes are structured.


Choice 2:
Just do exactly what you are doing and fake the
relationships. Subclass CayenneContext so that you can
create the appropriate setters and getters to make this all
work. We do this ourselves and I might be able to dig up
some code if you get stuck.
Are there any examples about this around?

You could download the onCourse server from our website (www.ish.com.au/oncourse) and open it up. Maybe download the Linux version since you can then easily unzip the jar (the Windows one is bundled in exe wrappers). Inside there you'll find our Cayenne model for the application (use version 3 modeler to look at it). And in there, some tables called Node and NodeRelation are of interest to you. In the application itself, we use this to display 'Tags' attached to lots of different entities: courses, students, etc.

Here's a snippet of code which then let's you find the related records. In this Taggable is the interface, Node the "Tag" entity and NodeRelation the join to other entities.

The main problem with it is that it doesn't scale well when you have 10,000 joins from one tag. The WHERE IN (...) sql clause doesn't scale well with all databases. Inheritance can certainly be faster and simpler.


        /**
         * Get a list of entity objects which are related to this node.
         *
* @param types restrict the entities which are to be returned to these classes
         * @return list of related objects
         */
public List<CayenneDataObject> getRelatedObjects(final Class<? extends Taggable>[] types) {
                final List<NodeRelation> relations = getNodeRelations();
final LinkedList<CayenneDataObject> result = new LinkedList<CayenneDataObject>();

                // iterate through each of the types we are looking for
                for (final Class<? extends Taggable> classToFind : types) {

                        // now build a list of ids to find
                        String nodeIDs = null;
                        for (final NodeRelation relation : relations) {
if (NodeRequirement .getTaggableClasses ().get(classToFind).equals(relation.getEntityIdentifier())) {
                                        if (nodeIDs != null) {
                                                nodeIDs = nodeIDs + ",";
                                        }
                                        nodeIDs = nodeIDs + " " + 
relation.getEntityRecordId();
                                }
                        }

                        final HashMap<String, String> map = new HashMap<String, 
String>();
map.put("entityName", NodeRequirement.getTaggableClasses().get(getClass()).toString()); final ObjEntity entity = getObjectContext().getEntityResolver().lookupObjEntity(classToFind);
                        String whereString = "";
                        if (entity.getAttribute(_Course.IS_DELETED_PROPERTY) != 
null) {
whereString = "WHERE ((" + _Course.IS_DELETED_PROPERTY + " is NULL OR " + _Course.IS_DELETED_PROPERTY + " = 0) AND id IN (" + nodeIDs + "))";
                        } else {
                                whereString = "WHERE id IN (" + nodeIDs + ")";
                        }
                        map.put("whereClause", whereString);

final List<CayenneDataObject> list = getObjectContext().performQuery(new NamedQuery("ObjectQuery", map));
                        if (list != null) {
                                result.addAll(list);
                        }
                }

                return result;
        }

Ari Maniatis



-------------------------->
ish
http://www.ish.com.au
Level 1, 30 Wilson Street Newtown 2042 Australia
phone +61 2 9550 5001   fax +61 2 9550 4001
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A


Reply via email to