From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-14 07:27:33
|
Hi Paul, Hibernate's associations are fundamentally uni-directional. The reason for this is that Java object references and the Java collections framework only permit navigation in one direction ie. dereferencing an object reference, or retrieving an object from a collection. There is no way for an object to determine if it belongs to a collection, or what other objects hold references to it. It is _possible_ to implement a bidirectional association in Java as a seperate class. At one (very early) stage there was even something exactly like this in Hibernate. I threw the concept away because it is just too alien to idiomatic Java. Now, it *would* be possible to do something like you suggest, and have two seperate associations, which happen to map to the same database column. The problem with that is that such a solution is very, very bugprone. If your Master throws away the Set it was holding details in, and creates a new Set, the details objects will still have references to the same Master. When we come to persist this broken structure, the results will be nondeterministic. Well, actually I lie. It *is* deterministic. The one-to-many association always wins over the many-to-one association in the current implementation. Those semantics are not guaranteed under a future, more efficient, implementation of collections. There is _no_ way to fix this without creating new API classes that intrude upon the business model. Or otherwise annoy you. For example, you wouldnt be able to pass collections seamlessly from one object to another and stuff like that.... If you really need a bi-directional association (if bi-directional associations were really that essential then OO languages would have them - and none do) then you can do any of the following 1. Detail has a many-to-one association to Master. Master can select its Details using a query ( perhaps lazily, perhaps from PersistentLifecycle.load() ) FROM detail IN CLASS pkg.Detail WHERE detail.master.id = ? and then put them in a transient collection. (My favored solution.) 2. Master has a one-to-many association to Detail. Detail can get its Master using a query (not efficient). 3. Master has a one-to-many association to Detail. Master can set transient backpointers on each Detail from PersistentLifecycle.load() All these solutions run the same risk of bugs as if they would be implemented in the persistence layer. The difference is: they would be application bugs - the persistence layer will still behave deterministically. I _guess_ we could fix the Schema generator to detect and remove duplicated column names and let you do what you want to do .... It won't *break* Hibernate, and it _does_ have quite str8forward semantics in this version (ie. the bit about the collection end wining.) But if we fix it I would much rather leave that feature undocumented. What do others think? Gavin |