Hi all.
I'ld like to do a question.. I have tried to use the ThreadLocal Pattern in my application. I have written this Java class:
Code:
import org.apache.log4j.Logger;
import it.eng.hibernate.exception.DBSessionException;
import it.eng.hibernate.exception.TransactionException;
import net.sf.hibernate.FlushMode;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.Transaction;
public class DBSessionMgr implements TransactionalResource {
private static final Logger LOG = Logger.getLogger(DBSessionMgr.class.getName());
private static ThreadLocal localSession = new ThreadLocal();
private static ThreadLocal localTransaction = new ThreadLocal();
private static SessionFactory sessionFactory;
/**
* @inheritDoc
*/
public synchronized void beginTransaction() throws TransactionException {
if (sessionFactory == null) {
throw new TransactionException("This transaction resource has not been initialized, please " + "initialize it first.");
}
if (localSession != null && localSession.get() != null) {
LOG.info("Encountered a pending transaction, commiting it before starting a new one.");
commitTransaction();
}
Session session;
Transaction tx;
try {
session = sessionFactory.openSession();
session.setFlushMode(FlushMode.AUTO);
tx = session.beginTransaction();
} catch (HibernateException e) {
LOG.error("Could not initialize the persistence.", e);
throw new TransactionException(e);
}
localSession.set(session);
localTransaction.set(tx);
LOG.info("Beginning transaction with thread : " + Thread.currentThread() + " and session " + session);
}
/**
* @inheritDoc
*/
public void initialize(String nomeFile) throws TransactionException {
if (sessionFactory == null) {
try {
if (nomeFile == null || nomeFile.trim().equals("")) {
LOG.debug("Using default configuration file");
sessionFactory = new Configuration().configure().buildSessionFactory();
} else {
LOG.debug("Using this file: [" + nomeFile + "]");
sessionFactory = new Configuration().configure(Thread.currentThread().getContextClassLoader().getResource("edilizia.cfg.xml")).buildSessionFactory();
}
} catch (HibernateException e) {
LOG.error("Could not initialize or configure the persistence factory.", e);
throw new TransactionException(e);
}
}
}
/**
* @inheritDoc
*/
public synchronized void commitTransaction() throws TransactionException {
Transaction tx = (Transaction) localTransaction.get();
Session session = (Session) localSession.get();
try {
tx.commit();
} catch (Exception e) {
LOG.error("Error closing the persistence when committing.", e);
rollbackTransaction();
throw new TransactionException(e);
} finally {
try {
session.close();
} catch (HibernateException e) {
LOG.fatal("Session could not be closed !!!", e);
}
localSession.set(null);
localTransaction.set(null);
}
LOG.info("Commiting transaction with thread : " + Thread.currentThread());
}
/**
* @inheritDoc
*/
public synchronized void rollbackTransaction() throws TransactionException {
Transaction tx = (Transaction) localTransaction.get();
if (tx != null) {
try {
tx.rollback();
} catch (Exception he) {
LOG.error("Exception while rollbacking", he);
throw new TransactionException(he);
}
}
LOG.info("Rollbacking transaction with thread : " + Thread.currentThread());
}
/**
* Metodo che controlla se c'è una transazione in atto
* @return boolean- true se c'è una transazione, false altrimenti.
*/
public synchronized boolean hasTransaction() {
if (localSession == null || localSession.get() == null) {
return false;
}
if (localTransaction == null || localTransaction.get() == null) {
return false;
}
return true;
}
/**
* Ritorna la sessione attualmente attiva
* @return -La sessione di Hibernate
* @throws DBSessionException -se la sessione o la localsession sono null
*/
public synchronized static Session getActiveSession() throws DBSessionException {
if (localSession == null) {
throw new DBSessionException("No active persistence, the transaction has probably not been initialized " + "in thread " + Thread.currentThread());
}
Session session = (Session) localSession.get();
if (session == null) {
throw new DBSessionException("No active session, the session has probably not been initialized in thread " + Thread.currentThread());
}
return session;
}
/**
* Ritorna la sessione attualmente attiva
* @return -La sessione di Hibernate
* @throws DBSessionException -se la sessione o la localsession sono null
*/
public synchronized static void closeActiveSession() throws DBSessionException {
if (localSession == null) {
throw new DBSessionException("No active persistence, the transaction has probably not been initialized " + "in thread " + Thread.currentThread());
}
Session session = (Session) localSession.get();
if (session == null) {
throw new DBSessionException("No active session, the session has probably not been initialized in thread " + Thread.currentThread());
}
try {
session.close();
} catch (HibernateException ex) {
throw new DBSessionException("Exception while closing session in thread " + Thread.currentThread() + " " + ex, ex);
}
localSession.set(null);
}
public synchronized static boolean hasActiveLocalSession(){
return ( localSession != null && localSession.get() != null );
}
/**
* Apro la sessione
* @return -la Sessione
* @throws DBSessionException -se ci sono errori nel connettersi al DB
*/
public static Session getDBReadSession() throws DBSessionException {
Session session = null;
try {
session = sessionFactory.openSession();
} catch (HibernateException e) {
throw new DBSessionException("Error while opening session. " + e.getMessage(), e);
}
return session;
}
/**
* Chiudo la sessione
* @param session -la sessione da chiudere
* @throws DBSessionException -Se ci sono errori.
*/
public static void closeDBReadSession(Session session) throws DBSessionException {
try {
session.flush();
session.close();
} catch (HibernateException e) {
throw new DBSessionException("Error while closing session." + e.getMessage(), e);
}
}
}
As you can see i use two ThreadLocal properties. Well i have thought to do in this way:
when there is a commit of a transaction in my finally block i close the local session and i empty the ThreadLocal property.
Now i'm new in hibernate and i'ld like to ask if this is a rigth approach in using this pattern or if there is a better way to use this pattern.
Thanks to all.
Angelo[/code]