From: Anton v. S. <an...@ap...> - 2002-05-27 03:49:01
|
I've checked in an initial, quite minimal version of the transaction changes. This message is mainly for Gavin's benefit, but if anyone else wants to follow along or comment, the gory details follow. There are only two small changes to existing code, both in the cirrus.hibernate package. Existing client code should be unaffected by this, so the change is completely optional for users. The changes are summarized below, for convenience. I've included the actual source code (minus comments), except for the two new classes, since it's so short and summarizes the changes well. I'll send a separate message with some design issues that I have questions about. In Hibernate.java, the following two methods were added: public static TransactionFactory buildTransactionFactory() throws HibernateException { return new TransactionFactoryImpl(); } public static TransactionFactory buildTransactionFactory(Properties transactionProps) throws HibernateException { return new TransactionFactoryImpl(transactionProps); } In Environment.java, the following definition was added: public static final String TRANSACTION_STRATEGY = "hibernate.transaction_strategy"; In addition to the above, there are two new public interfaces in cirrus.hibernate: public interface Transaction { public void commit() throws HibernateException; public void rollback() throws HibernateException; } public interface TransactionFactory { public Transaction beginTransaction(Session session) throws HibernateException; } Then there's a new package, cirrus.hibernate.transaction. This contains one "internal" interface: interface TransactionImplementor extends Transaction { public void begin(Session session) throws HibernateException; } cirrus.hibernate.transaction also contains two new classes, so far: class TransactionFactoryImpl implements TransactionFactory; class JDBCTransaction implements TransactionImplementor; That's it. I also added a line to the changelog under 0.9.14. I haven't yet implemented JTATransaction or CMTTransaction, although obviously they ought to be pretty simple (if not completely empty). I've performed only limited tests so far, to make sure my own application could use the new functionality, and that existing code didn't break. Of course, the changes are such that existing code is unlikely to be affected. Let me know if I've forgotten anything. Feel free to change anything at all, or if you'd like me to make particular changes. I'm going to be doing some work integrating into my own application, and will enhance the transaction code as necessary, as I go along. Anton |
From: Anton v. S. <an...@ap...> - 2002-05-27 05:24:57
|
Some points which I want to mention about my new code: * The mechanism for choosing an xxxTransaction class is very simple: it reads a property called hibernate.transaction_strategy, which has a default value of "JDBC"; it appends the string "Transaction" to the result, and tries to load a class with that name, from the cirrus.hibernate.transaction package. By default, it will therefore try to load the JDBCTransaction class. The default strategy (JDBC) and classname base (Transaction) are hardcoded in the TransactionFactoryImpl class. This could easily be made more flexible, but I don't think it's essential at this stage. Also, making the default strategy a property seemed kind of pointless. It might make more sense for the classname base and package name, but I didn't want to madly start adding unnecessary properties, especially if the class selection mechanism changes. * Should buildTransactionFactory() be named createTransactionFactory? I don't really care, just wanted to mention it since both were discussed at one point. Better yet, see following point. * Saving the best till last (you're going to hate me): I still think there's a good case for putting the beginTransaction() factory method on the Session interface (but leaving the rest of the external design the same). The justification for this: o beginTransaction() currently needs to be passed a Session object, because of the close association between the two classes. o Within Hibernate, it won't really be meaningful to have a Transaction without a Session (although a Session without a Transaction is OK). o It would eliminate the need for the user to explicitly create a TransactionFactory, and make it accessible throughout the application, in addition to the SessionFactory. The interface needed by the user is simplified. o It makes sense implementation-wise, and doesn't lose any needed flexibility. I would probably keep the existing classes, to maintain clear design separation, but have SessionFactory maintain an internal reference to a TransactionFactory. RelationalDatabaseSession would then implement beginTransaction() using something like: return factory.getTransactionFactory().createTransaction(this); o Support for other TransactionFactories, like JTATransactionFactory, could still be handled in whatever way we decide, as long as it's driven by properties (the ones passed to buildSessionFactory or the default properties), i.e. as long as there's no reason for the user to interact directly with the creation of the TransactionFactory. With this change, the client idiom would become: // no longer needed: // TransactionFactory tf = Hibernate.buildTransactionFactory(); Session s = sf.openSession(); Transaction t = s.beginTransaction(); // was tf.beginTransaction(s) try { Foo foo = s.load(fooid); foo.setName("FOO"); t.commit(); } catch (Exception e) { t.rollback(); } finally { s.close(); } My fingers are itching... ;) Anton |