Hello,
After reading docs, I've decided to implement session-per-request-with-detached-objects strategy with JTA managing transactions. I think I should really be using an appserver, but I am constrained by having to use Tomcat 5.5/JOTM. Also, I am running unit tests in standalone mode, so I cannot rely on a servlet filter to abstract tx management code (especially the exceptions). Could someone please give me a yes/no on the following:
1. Since I'm implementing session-per-request with JTA, I cannot use Hibernate's Transaction API, and must use javax.transaction.UserTransaction directly. Yes/No?
"If you want to use a transaction-bound Session, that is, the getCurrentSession() functionality for easy context
propagation, you will have to use the JTA UserTransaction API directly:" - Hibernate Ref PDF, p127.
2. If #1 is true, what is the purpose of <property name="jta.UserTransaction">java:comp/UserTransaction</property> in hibernate.cfg.xml. (I will have to explicitly lookup UserTransaction anyway). Can I remove this property?
3. UserTransaction.begin() and UserTransaction.commit() both throw a boatload of exceptions. Since I can't use Hibernate API and Servlet Filter is not an option how can I abstract tx.begin and tx.commit? Is "AOP interceptor" (not sure how that works but looks hairy ;- ) my only option?
Here's how my persistence method looks like w/o tx abstraction:
Please note the comment above 'catch'.
Code:
public void someBusinessOperation()
{
try {
//lookup tx
UserTransaction tx = (UserTransaction)new InitialContext()
.lookup("java:comp/UserTransaction");
//start tx - throws 3-4 exceptions
tx.begin();
// Do some work on Session bound to transaction
factory = HibernateUtil.getSessionFactory()
factory.getCurrentSession().load(...);
factory.getCurrentSession().persist(...);
//commit tx - throws 5 exceptions
tx.commit();
}
//catch 8 different exceptions that begin() and commit() throw
catch (RuntimeException e) {
tx.rollback();
throw e; // or display error message
}
}
thanks a lot,
-nikita
HibernateUtil Code:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
private static final Logger logger =
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
logger.fine("Evilsite SessionFactory configured");
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
logger.severe("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Hibernate version: 3.1
hibernate.cfg.xmlCode:
<hibernate-configuration>
<session-factory>
<!-- Settings for local MySQL database. -->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="connection.datasource">java:comp/env/jdbc/EvilsiteDB</property>
<!-- Disable second-level cache. -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Print SQL to stdout. -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Bind the getCurrentSession() method to JTA. -->
<property name="current_session_context_class">jta</property>
<property name="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.JOTMTransactionManagerLookup
</property>
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
<!-- JTA transaction name, as defined in context.xml -->
<property name="jta.UserTransaction">
java:comp/UserTransaction
</property>
<!-- Make Hibernate aggresively release cnxs after every jdbc call-->
<property name="hibernate.connection.release_mode">
after_statement
</property>
<!-- Hibernate XML mapping files -->
<mapping resource="net/eviltwinstudios/beans/WebUser.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Code between sessionFactory.openSession() and session.close():