From: Sven W. <s_...@in...> - 2002-03-15 23:33:34
|
> > If you want to use hibernate with stateless session beans you have to > make > > sure that you do everything at once within the session bean because when > > the object under (hibernate)session control leaves the (ejb)session bean > > via serialization there is no way to get this object back into the > database. > > Stated slightly differently: We would like to be able to replace the state > of > a persistent instance with the state of a transient instance. Ok, this is what I meant. > This raises (at least) the following issues: > > (1) Does the "state" of the transient instance include it's id? Since > hibernate allows the Session to track id's, I'm thinking, on the face > of it, the answer is "no". Hmm, this raises the question: How do I find the old record in the database ? So, the answer is "yes" because ID is usually a property that is stored inside the transient/persisted object. > (2) Does the "state" of the transient instance include it's version number? > I'm thinking the answer is to this would be "yes". Yes, a version number would really help. But we have to be aware that having a single version number does _not_ guarantee serializability (there are phantom reads and non repeatable reads). Ok, it is possible to set the transaction isolation in the jdbc driver to serializable but then the question appears why having version numbers at all. Sometimes it is useful to allow non versioned objects because there might be a different approach to concurrency control for existing systems that is unknown to hibernate (e.g combination of different timestamp columns). > (3) Should replacement replace the actual instance, or just copy its state > into the current persistent instance? I'm thinking: always do a copy. Sorry, I don't see a difference between replace and copy (may be my english :) If you're thinking: the updated record in the database has the same id as before I'm with you. > (4) (Most Difficult) Where should replacement *stop*? To be very consistent > with the current semantics of hibernate, it should probably just copy state > from one entity (+ collections + components), rather than walking the graph > of associated entities. However, this makes collections of entities quite > difficult to use. The application itself would have to decide when to add > new collection elements and when to update existing ones. My thinking on > this is we should provide single object replacement at present, and leave > the more difficult problem for later when/if we really start to address the > "persistence-by-reachability" problem. I think it should be possible to persist single objects and a set of single objects at once because: * updating single objects is easy to implement * writing a special collection class with special add/update/remove operations is also easy to implement * persisting a collection of single objects is a very common operation I don't think that having the possibility to persist large and complex object graphs is really necessary for everyday usage but would be a "nice thing to have". > (5) If the transient instance contains references to other transient > instances, we at least need to figure out if some of these are actually > references to existing persistent instances and resolve those references. > This would only be possible if the transient instances hold their id. > So i guess my initial answer to (1) is wrong and we should only allow > replacements for classes which have identifier properties. Is it possible to have objects without an identifier ? Are there examples where this might be useful ? (for non read-only objects) > Hibernate has a sophisticated mechanism for extracting the persistent state > of an instance, so I'm not seeing a really strong need for the Moveable > interface. For simple objects this is true but if there are complex object graphs the situation may be different. Currently I do not know enough about the interna of hibernate to prove this as right or wrong. > > but for "Movable" objects it should be possible to get the old state > > without the need of a real session. > > For some movable objects it might be useful to do not keep an additional > > state because you know when these objects are dirty which saves bandwidth > > and coding time. > > I don't see a really compelling argument that this is something hibernate > should provide. Yes, it would save a query to fetch the clean state of the > instance but on the other hand it is very model-intrusive and wastes > bandwidth as you noted. It may also subtly influence the transaction > isolation semantics. You always trade database I/O for bandwidth but it is impossible to say which solution is _the_ best because sometimes you don't have bandwidth and sometimes the database I/O is critical. So, supporting both does not hurt. For the transaction isolation I don't see where it increases or decreases isolation. If you want to compare the old vs. new version the old version should always be the version that was loaded originally. > > Non versioned writes should also be allowed: (e.g. this is > > useful if you want to do cross database replication between different > > application servers). > > Not quite sure what you are describing here. If you do not use hibernate with a brand new database schema there might be already some different fields/columns that are used for concurrency control. You have to be compatible with these fields and do concurrency checks inside your application code. > To sum up, my suggested API would be: > > public interface Session { > .... > public Object update(Object replacement); > .... > } > > we would pass in a transient instance with an id property and > receive back the corresponding persistent instance, with its state > already updated. Perhaps we could allow the variant: > > public Object update(Serializable id, Object replacement) > > for objects without id properties. > > Any problems with this approach? No. But I would like to see the following additional: // to save database I/O public Object update (Object replacement, Object replacementAfterLoad); // or how about this ? public Object update (Object replacement, boolean isDirty); // to save a set of simple objects public void update (SpecialHibernateMap objectsToUpdate); bye Sven |