[OJB-developers] Question regarding extents
Brought to you by:
thma
From: Matthew b. <mat...@ya...> - 2002-05-30 06:46:26
|
I'm looking through the code trying to thoroughly grok how extents are supported, and I have to admit I'm a little bit puzzled :) I was wondering if someone out there could comment on my understanding of how things work: Consider having two objects mapped to the same table, but they one doesn't inherit from the other. To be concrete, we have OperatingUnit and EnterpriseUnit. If I execute an OQL query "select unit from com.somecompany.OperatingUnit" I would expect to get back all the operatingunits and none of the enterpriseunits. To support that, I've included an ojbConcreteClass mapping for each of the unit types. OJB does it's thing and finally ends up calling the .next() on the RsIterator, during which OJB will call getObjectFromResultSet which will eventually call readObjectFrom readObjectFrom then checks the ojbConcreteClass attribute, but can't really use this as a discriminator since it doesn't know what you asked for (for instance, the first row in the UNIT table is an enterprise unit, and I asked for operatingunits) so it tries to build the EnterpriseUnit using the query results of the OperatingUnit. If EnterpriseUnit doesn't have the same fields mapped in the same order as OperatingUnit, building the new instance of the object will throw an exception. the exception makes its way back to the .next() routine where it is caught as an Exception and rethrown as a NoSuchElementException which is NOT caught in getCollectionByQuery getCollectionByQuery is extent aware, and is ready to deal with having object materialized that don't match what was asked for if ((itemClass.equals(candidate.getClass())) || (Proxy.isProxyClass(candidate.getClass())) || (candidate instanceof VirtualProxy)) is the important peice of code however, this code is unlikely to actually be called because Object candidate = i.next(); is probably going to throw a NoSuchElementException exception. There are a couple other places where we load the object, check the type and try to materialize one of those objects. Using the new row[] array instead of the resultset means we have to be aware of the ordering of results (we can't get them by name) which causes a problem with 2 objects mapped to the same table with different order of mappings. I can live with that, but the materialization of an extent object with extra attributes failing because row[] doesn't contain all those values is not good. If you grokked all that, here's a potential solution: when creating the select SQL, if more than one object is mapped to the table, either load the union of all the fields that *could* be used dependent on object type, then store them by name in a hashmap (or come up with a lighter solution to get the columns by name). Then you would be guaranteed that the actual object could be created if need be. This solution would allow for people to query on base class and still get back base and sub classes all mapped to same table. Other solution would be to somehow append the objConcreteClass discriminator to the where clause, but that would not allow for loading subclasses as base objects, so I don't think it's a good solution. Comments? --------------------------------- Do You Yahoo!? Yahoo! - Official partner of 2002 FIFA World Cup |