Hi all
I've written code catering to multiple database connection. Am posting it here for everyone future reference.
Few pre-processing notes:
[hbmMap] Due to the modular nature of my project, the hbm.xml are specified in a custom cfg file instead of normal hibernate.cfg.xml. I pre-processed hbm.xml into map of
{DB_INSTANCE,hbm list} i.e.
{"default", ["User.hbm.xml","Role.hbm.xml"]}
{"report", ["Journal.hbm.xml"]}
[DB_INSTANCE.db.xml] Every db instance must have a DB_INSTANCE.db.xml in WEB-INF/classes path. To simplify the lookup, the DB_INSTANCE matches that of hbmMap. So for this example, I will have default.hbm.xml and report.hbm.xml in classes path. This db.xml is exact of hibernate.cfg.xml (renamed as *.cfg.xml is reserved for other setting).
I am still evaluating the following points:
- performance of session / sessionFactory maintained in map
- impact of map to ThreadLocal session
Appreciate if someone can help vet through and comment.
Code:
public class HibernateUtil
{
// Logger initialization
private static final Log LOG = LogFactory.getLog(HibernateUtil.class);
// map that holds sessionFactory
private static Map<String,SessionFactory> sessionFactory = new HashMap<String,SessionFactory>();
// map that holds current open sessions
public static final Map<String,ThreadLocal<Session>>session = new HashMap<String,ThreadLocal<Session>>();
public static void initSession(Map<String,List<String>> hbmMap, ClassLoader mainClass)
throws HibernateException, java.io.IOException {
//======================================================================================
// to handle multiple database connections,
// 1. [instance].db.xml specify db properties
// 2. mapping in *.cfg.xml specify which db the hbm belongs to via db attribute (default if not specified)
// 3. CfgLoader generates hbmMap, where KEY=db name, and VALUE=hbm list
// 4. Each db goes into seperate sessionFactory
//======================================================================================
// for each db instance in the configuration
for(String instance : hbmMap.keySet() ) {
try {
if(session.get(instance) == null) {
Configuration cfg = new Configuration();
LOG.info(" : ---------- " + instance + " ----------");
// load the hbmList
for(String hbmFile : hbmMap.get(instance)) {
LOG.info(" : " + hbmFile);
cfg.addResource(hbmFile, mainClass);
}
// create session factory
SessionFactory sf = cfg.configure("/" +instance+ ".db.xml").buildSessionFactory();
sessionFactory.put(instance, sf);
session.put(instance, new ThreadLocal<Session>());
} else {
LogFactory.getLog(HibernateUtil.class).info("Session [" +instance+ "] already initialized");
}
} catch (HibernateException ex) {
LOG.error(ex);
throw new RuntimeException("Configuration problem: " + ex.getMessage(), ex);
}
}
}
//--------------------------------------------------------------------------
// this open the default session
//--------------------------------------------------------------------------
public static Session currentSession() throws HibernateException {
return currentSession("default");
}
//--------------------------------------------------------------------------
// this close default session
//--------------------------------------------------------------------------
public static void closeSession() throws HibernateException {
closeSession("default");
}
//--------------------------------------------------------------------------
// open session from named instance
//--------------------------------------------------------------------------
public static Session currentSession(String instance) throws HibernateException {
Session s = (Session) session.get(instance).get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.get(instance).openSession();
session.get(instance).set(s);
}
return s;
}
//--------------------------------------------------------------------------
// close session from named instance
//--------------------------------------------------------------------------
public static void closeSession(String instance) throws HibernateException {
Session s = (Session) session.get(instance).get();
session.get(instance).set(null);
if (s != null)
s.close();
}
}