From: Anton v. S. <an...@ap...> - 2002-05-17 21:52:07
|
> hhmmmmmmm .... damn this is all coming back to haunt ..... Sorry to rehash - I hadn't seen the previous discussion. I'll check out the archives to catch up, although I haven't yet done so in the response below. > Lets state the problem carefully: > > What API allows the user to END a Session and > > (1) is easy to use and understand for new users, > (2) has methods with clear semantics, > (3) supports the various different possible styles of connection + > transaction management eg. application server datasource + JTA, > DriverManager + Connection.commit(), long transactions, > (4) comforms to the philosophy that Hibernate is a thin wrapper > around JDBC that exposes all underlying JDBC functionality to > the application. (A wrapper with "windows"?) I agree with all of that. I'm proposing two additional requirements, one of which I stated explicitly and one of which I didn't (but should have). The one I stated explicitly was: > application code could switch the underlying transaction > handling mechanism without changing the client code Aside from the convenience of this, I think that the current design with session.connection().xxx encourages users to depend on direct access to the Connection, and doesn't provide an alternative. In a sense, this leads users down the wrong path - Hibernate abstracts all sorts of things but then just exposes the connection and encourages its use. I'm all for the idea of "a wrapper with windows", but I'm also suggesting that it shouldn't be necessary to use those windows. It should be an option for those who want it. My second requirement comes from never having been a fan of the JDBC transaction API, and its reliance on toggling autoCommit to begin and end transactions. This is unintuitive, doesn't "say what it means", and can have bad consequences in the case of mistakes. For example, forgetting to setAutoCommit(true) at the end of a transaction results in all subsequent requests on that connection being lumped into a single transaction, with potentially horrible effects on concurrency. I'm suggesting that a very thin wrapper here would be beneficial in general, and I think it's appropriate for Hibernate to offer this as an optional alternative, to encourage sensible transaction usage that reads well in the application code, guards against certain kinds of errors, and corrects the egregious mistakes that Sun made. ;) If the above two additional requirements are met, I'm not as concerned about the exact form this API takes. OTOH, if everyone thinks I've been smoking the $2 crack, I'll stick to using my own wrapper to get the functionality I want. What prompted me to start this thread was the questions that have arisen about what Sessions are, and the attempt to clarify them in documentation. I think part of the problem is that the relationship between a Session and a transaction isn't as clear as it might be, and this is at least partly because the separation between the two is currently implemented by saying "here's the connection, you're on your own with transactions". I imagine this is likely to encourage the tendency of users to think of a session as being like a connection, which you can use repeatedly for multiple transactions. I think that making it unnecessary to directly access the connection would be of general benefit to Hibernate users, and as a side benefit, may be less likely to result in confusion, although obviously that's just a guess. It would still be necessary to make it clear, for example, that multiple transactions shouldn't be executed on a single session. I suppose commitTransaction() and rollbackTransaction() could also simply close the connection - more on this below. > When we had this discussion earlier, Brad Clow commented that one > thing that was so confusing was that we were overloading the word > "commit" to mean something other than committing a transaction. > I agreed at the time, and still agree. If we do something like > you are suggesting, we should not use the words "commit", "begin" > "rollback" or "transaction" anywhere on the Session interface. That was why I suggested method names like "commitTransaction". My intent was to clearly delineate between operations on the Hibernate Session, and the conceptual/database transaction. I was also trying to stick more closely to the current API's approach, and basically suggesting that session.connection().commit() could simply be (optionally) replaced by session.commitTransaction(), which would buy some additional abstraction and thus flexibility. My suggestion actually doesn't change the current API all that much, and of course the existing API could still be used as is, i.e. it's a backwards-compatible addition. > public interface Session { > ..... > public void end() throws ....; //commit, close > public void cancel() throws ....; //rollback, close > public void pause() throws ....; //commit, disconnect > public void resume() throws .....; //reconnect > } This would satisfy my concerns above in terms of its functionality. I have two further observations: 1. The begin/commit/rollback idiom is pretty well known and understood. Essentially making up new words for these doesn't necessarily help new users. 2. I do see some benefit to separating the transaction functionality from the session. For example (and perhaps I just need more info here): what about the case where a session will be "read-only", so that an explicit overall transaction isn't needed, i.e. equivalent to JDBC setAutoCommit(true)? If an overall transaction is implicitly created by Hibernate, it could reduce concurrency unnecessarily. This was one reason why I thought it might be a good idea to separate out the transaction calls from the session open/close. A readonly session could simply omit the transaction calls, and perhaps include an initial call to suspendFlushes(), for example. I think this might be simpler than adding features to the above API to support this case. > I'm also not keen on changing the cirrus.hibernate.Session interface again > at this stage. It might be preferable to develop this API (ie. the new > Session and SessionFactory interfaces) in a seperate package. Say, > cirrus.hibernate.4dummies or something. ;-> The new functionality could be > implemented either on the existing cirrus.hibernate.impl classes or as > wrapper classes that delegate to cirrus.hibernate.SessionFactory and > cirrus.hibernate.Session. I'm sensitive to this concern. Again, that was a reason I proposed adding xxxTransaction() to Session, since it wouldn't break existing code, and it could be an optional mechanism. If the other approach is decided on, making a Session the same as a transaction, perhaps an alternative to Session would be needed. I'm being very outspoken for a brand new Hibernate user working on his first application with it. All Gavin's fault for encouraging me. :) If I'm missing something or am wrong about this, please apply cluestick to my noggin with appropriate force. But even if my conclusions aren't palatable, I think at least the concern about wrapping connections has validity, and I'd be interested in figuring out (and working on) a sufficiently general way to address that. Anton |