From: Gavin_King/Cirrus%<CI...@ci...> - 2002-05-17 07:19:48
|
> I know that commit() and cancel() were recently deprecated, but > I'm thinking it might be a good idea to add some methods for a > slightly more general transaction handling mechanism to the Session > class. hhmmmmmmm .... damn this is all coming back to haunt ..... 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"?) The old approach with Session.commit() + Session.cancel() tried to be a great solution to (1) but because it miserably failed at (2) ended up being very confusing for _all_ users. The new API is a much better solution in terms of (2), (3) and (4) - particularly (2) - but still requires a fairly lengthy explanation about how to actually end a Session - something that should, on the face of it, be so damn simple!! > What I have in mind is that Session would support at least three > additional methods, something like beginTransaction, > commitTransaction, and rollbackTransaction. These would delegate > to an object which implements a "SimpleTransactionManager" interface > with those methods. 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. I would suggest something along the lines of: public interface TransactionStrategy { public Connection begin() throws ....; // fetch a connection public void commit(Connection connection) throws ...; // commit, close connection public void rollback(Connection connection) throws ....; // rollback, close connection } 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 } Then client code could look like: Session s = factory.openSession(sessionLifecycle); try { //do some work .... s.flush(); } catch (Exception e) s.cancel(); throw e; } s.end(); Session.pause() and Session.resume() would be used to disconnect and reconnect. > Hibernate could supply a couple of really > simple implementations of this interface, e.g. one which just maps > to JDBC calls, and The implementations I can think of would be: DriverManagerTransactionStrategy JTADatasourceTransactionStrategy NonJTADatasourceTransactionStrategy > perhaps one which maps to "BEGIN TRAN", "COMMIT > TRAN", "ROLLBACK TRAN" statements as appropriate for the SQL > dialect. JDBC already does this mapping, by providing Connection.commit() and Connection.rollback() ... > application code could switch the underlying transaction > handling mechanism without changing the client code This is a 'new' requirement that is not implemented by the current API. It seems a worthwhile addition.... > IMO, the transaction-handling idiom would become a bit neater > and better abstracted: > > Session sess = factory.openSession(); > try { > sess.beginTransaction(); > //do some work > ... > sess.commitTransaction(); > } > catch (Exception e) { > sess.rollbackTransaction(); > throw e; > } > finally { > sess.close(); > } I need more opinions upon which API is better. flush(), end(), cancel() OR commitTransaction(), rollbackTransaction(), close() 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. After all this thinking, I'm still not 100% convinced we should go down this path..... (or not yet, anyway). If there is a general clamor of agreement that this is a much better solution, I guess we should take it. However, this may just be increasing the complexity of our API to fix a problem (hard for new users to understand) that would be just as easily fixed by better documentation. We have so far managed to cram a large amount of functionality into a very, very narrow API. This is a Good Thing. Adding new APIs now might not be.... undecided.... Gavin |