| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-06 08:39:25
      
     | 
| > Yes. I currently use Persistent in two ways. > > 1. When computing the inheritance graph. As classes are added to the > set to be analyzed, I construct this graph (well, actually a set of > trees since Java is single inheritance). The lack of a Peristent > interface tells me when to stop climbing superclass links to insure > that all requisite classes are included I take it you mean you stop climbing the tree looking for _classes_. Properties from superclasses _should_ be included.... I'm trying to think of a reason why _not_ to produce a mapping that includes non-persistent superclasses and the reason I can think of is because you want separate branches of the hierarchy to go in separate tables. I actually hadn't thought of this earlier... > 2. When determining the role of a property which is a reference to an > object. If the object's class implements Persistent, then it's an > association. Otherwise it's something else. Details below. This is the problem I _had_ thought of. How do we pick between a component and an entity class? > Currently it is only necessary to provide MappingByReflection the > fringe of the inheritance graph. We could insist that all classes to > be analyzed are provided, but this could lead to errors (missing > superclasses; holes in the graph -> extra tables which are too > sparse). I'm not against this solution. The things which look like problems could also be interpreted as "features" which give the user extra control. Asking the user to explicitly list all classes is actually less intrusive and logically equivalent to asking them to implement Persistent (well, excepting the possiblity for errors you raise). Another suggestion: One possible hueristic that "solves" both problems is to see if something there looks like an ID property. If theres none, its a component or a non-persistent superclass. A command line switch could even set a list of property names the user uses for IDs. I kind of like this solution because it isolates as much possible dodgy guessfulness in one single rule that the user can understand and control, rather than having ten different rules that interact in wierd and unpredictable ways. > Currently the following must be true of a class before it is added as > a persistent [super]class: > the class > C1. is not Primitive > C2. is not an Array > C3. is not an Interface > C4. is not nested (an inner class), i.e., c.getDeclaringClass() == null > C5. is not Abstract > C6. has a public default constructor (0 arguments) > C7. implements Persistent C3 I _guess_ is reasonable, though not essential. C5 I dont think is right. Hibernate itself doesnt care about the actual inheritence heirarchy and whether classes are instantiable. You could have an abstract class somewhere in the heirarchy of persistent classes. This is particularly important if we have Foo and Bar, both concrete classes, subclassing Baz, an abstract class, but we want to load foos and bars polymorphically from the database. Actually, the more I think about it, the more I think C3 should be dropped.... C6 is changed to: it has a default constructor of any visibility level. > What can we replace #7 with to limit the search? One possibility is > the class must be in the same toplevel package. E.g., system classes > would never be persistent. Opinions? Suggestions? hmmmm same toplevel package I hadn't thought of. Still not enough though, since we could still end up with everybody in the same table. Whatever we do we need to give the user _some_ way of indicating which classes go in the same table. > > Determining property roles is much more difficult. Currently I am > using the following heuristic, some of which is based on the logic in > Hibernate.auto... > > 1. Hibernate.basic(cls) != null => BASIC_KIND > 2. cls.isArray() => ARRAY_KIND > 3. Type.class.isAssignableFrom(cls) => CUSTOM_KIND; > 4. Persistent.class.isAssignableFrom(cls) => ASSOCIATION_KIND > 5. PersistentEnum.class.isAssignableFrom(cls) => ENUM_KIND > 6. java.util.List.class.isAssignableFrom(cls) => LIST_KIND > 7. java.util.Map.class.isAssignableFrom(cls) => MAP_KIND > 8. java.util.Set.class.isAssignableFrom(cls) => SET_KIND > 9. Serializable.class.isAssignableFrom(cls) => SERIALIZABLE_KIND > 10. else if C1..C6 above are true => COMPONENT_KIND > 11. else UNKNOWN_KIND (error) > > As Gavin points out, without Persistent, it is impossible to > distinguish ASSOCIATION_KIND from COMPONENT_KIND. > > But, the above heuristic has other problems. It cannot distinguish > SERIALIZABLE_KIND and COMPONENT_KIND -- the choice is arbitrary if > both modes are possible. It also cannot determine if collections and > arrays should be keyed (top level) or unkeyed. Nothing should default to Serializable. Its almost always a bad idea to store things in serialized form. (Unless they are, genuinely a stream of bytes. eg. a JPEG or something.) > It is also impossible for MappingByReflection to see inside lists, > maps, and sets. Because they must be declared by their basic > collection interface, the reflection code has no clue what they > contain. Yeah, they should be left simply as stubs for the user to fill in. Thats cool, if this tool does 70% of the work (the tedious work), it already takes away 90% of the pain :) > I plan to continue working on the MappingByReflection code in the hope > that someone will step forward to implement a GUI front end where some > of this missing information can be interactively supplied. Eventually we will need this. > As a snapshot of its current status, MappingByReflection produces the > XML output below given the args[]... > That looked brilliant! (Unfortunately some will have to change with the new hibernate-mapping DTD) |