在项目中使用多个数据源-多sessionFactory方案(转)
适用范围:适合SSH架构访问多个数据库,数据库的类型和表结构不必相同,且没有跨库事务的情况(跨库事务最好用分布式事务处理)。
实现方式:我们可以在spring的配置文件中配置多个sessionFactory,如:
<bean id="aDataSource"
?? />
?? </property>
?? <property name="mappingResources">
??? <list>
???? <value>
????? .hbm.xml文件
???? </value>
??? </list>
?? </property>
?? <property name="hibernateProperties">
??? <props>
???? <prop key="hibernate.dialect">
????? ${ahibernate.dialect}
???? </prop>
???? <prop key="hibernate.show_sql">true</prop>
???? <prop key="format_sql">true</prop>
??? </props>
?? </property>
</bean>
<bean id="bSessionFactory"
?? />
?? </property>
?? <property name="mappingResources">
??? <list>
???? <value>
????? .hbm.xml文件
???? </value>
??? </list>
?? </property>
?? <property name="hibernateProperties">
??? <props>
???? <prop key="hibernate.dialect">
????? ${bhibernate.dialect}
???? </prop>
???? <prop key="hibernate.show_sql">true</prop>
???? <prop key="format_sql">true</prop>
??? </props>
?? </property>
</bean>
<bean id="cSessionFactory"
?? />
?? </property>
?? <property name="mappingResources">
??? <list>
???? <value>
?????? .hbm.xml文件
???? </value>
??? </list>
?? </property>
?? <property name="hibernateProperties">
??? <props>
???? <prop key="hibernate.dialect">
????? ${chibernate.dialect}
???? </prop>
???? <prop key="hibernate.show_sql">true</prop>
???? <prop key="format_sql">true</prop>
??? </props>
?? </property>
</bean>
<bean id="sessionFactory" class="com.cintel.dcp.datasource.MultiSessionFactory">
?? <property name="sessionFactory"><ref local="aSessionFactory"/></property>
</bean>
注意:最后一个com.cintel.dcp.datasource.MultiSessionFactory要自己实现,它实现了SessionFactory接口和ApplicationContext接口,如下:
package com.cintel.dcp.datasource;
import java.io.Serializable;
import java.sql.Connection;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.Reference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.classic.Session;
import org.hibernate.engine.FilterDefinition;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.stat.Statistics;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MultiSessionFactory implements SessionFactory, ApplicationContextAware {
private static final long serialVersionUID = 2064557324203496378L;
private static final Log log = LogFactory.getLog(MultiSessionFactory.class);
private ApplicationContext applicationContext = null;
private SessionFactory sessionFactory = null;
public ApplicationContext getApplicationContext() {
?? return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) {
?? this.applicationContext = applicationContext;
}
public SessionFactory getSessionFactory(String sessionFactoryName) {
?? log.debug("sessionFactoryName:"+sessionFactoryName);
?? try{
??? if(sessionFactoryName==null||sessionFactoryName.equals("")){
???? return sessionFactory;
??? }
??? return (SessionFactory)this.getApplicationContext().getBean(sessionFactoryName);
?? }catch(NoSuchBeanDefinitionException ex){
??? throw new RuntimeException("There is not the sessionFactory <name:"+sessionFactoryName+"> in the applicationContext!");
?? }
}
public SessionFactory getSessionFactory() {
?? String sessionFactoryName = CustomerContextHolder.getCustomerType();
?? return getSessionFactory(sessionFactoryName);
}
public void setSessionFactory(SessionFactory sessionFactory) {
?? this.sessionFactory = sessionFactory;
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#close()
*/
public void close() throws HibernateException {
?? getSessionFactory().close();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evict(java.lang.Class)
*/
public void evict(Class persistentClass) throws HibernateException {
?? getSessionFactory().evict(persistentClass);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evict(java.lang.Class, java.io.Serializable)
*/
public void evict(Class persistentClass, Serializable id) throws HibernateException {
?? getSessionFactory().evict(persistentClass, id);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evictCollection(java.lang.String)
*/
public void evictCollection(String roleName) throws HibernateException {
?? getSessionFactory().evictCollection(roleName);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evictCollection(java.lang.String, java.io.Serializable)
*/
public void evictCollection(String roleName, Serializable id) throws HibernateException {
?? getSessionFactory().evictCollection(roleName, id);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evictEntity(java.lang.String)
*/
public void evictEntity(String entityName) throws HibernateException {
?? getSessionFactory().evictEntity(entityName);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evictEntity(java.lang.String, java.io.Serializable)
*/
public void evictEntity(String entityName, Serializable id) throws HibernateException {
?? getSessionFactory().evictEntity(entityName, id);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evictQueries()
*/
public void evictQueries() throws HibernateException {
?? getSessionFactory().evictQueries();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#evictQueries(java.lang.String)
*/
public void evictQueries(String cacheRegion) throws HibernateException {
?? getSessionFactory().evictQueries(cacheRegion);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getAllClassMetadata()
*/
public Map getAllClassMetadata() throws HibernateException {
?? return getSessionFactory().getAllClassMetadata();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getAllCollectionMetadata()
*/
public Map getAllCollectionMetadata() throws HibernateException {
?? return getSessionFactory().getAllCollectionMetadata();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getClassMetadata(java.lang.Class)
*/
public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException {
?? return getSessionFactory().getClassMetadata(persistentClass);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getClassMetadata(java.lang.String)
*/
public ClassMetadata getClassMetadata(String entityName) throws HibernateException {
?? return getSessionFactory().getClassMetadata(entityName);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getCollectionMetadata(java.lang.String)
*/
public CollectionMetadata getCollectionMetadata(String roleName) throws HibernateException {
?? return getSessionFactory().getCollectionMetadata(roleName);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getCurrentSession()
*/
public Session getCurrentSession() throws HibernateException {
?? return getSessionFactory().getCurrentSession();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getDefinedFilterNames()
*/
public Set getDefinedFilterNames() {
?? return getSessionFactory().getDefinedFilterNames();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getFilterDefinition(java.lang.String)
*/
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
?? return getSessionFactory().getFilterDefinition(filterName);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#getStatistics()
*/
public Statistics getStatistics() {
?? return getSessionFactory().getStatistics();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#isClosed()
*/
public boolean isClosed() {
?? return getSessionFactory().isClosed();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#openSession()
*/
public Session openSession() throws HibernateException {
?? return getSessionFactory().openSession();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#openSession(java.sql.Connection)
*/
public Session openSession(Connection connection) {
?? return getSessionFactory().openSession(connection);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#openSession(org.hibernate.Interceptor)
*/
public Session openSession(Interceptor interceptor) throws HibernateException {
?? return getSessionFactory().openSession(interceptor);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#openSession(java.sql.Connection, org.hibernate.Interceptor)
*/
public Session openSession(Connection connection, Interceptor interceptor) {
?? return getSessionFactory().openSession(connection, interceptor);
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#openStatelessSession()
*/
public StatelessSession openStatelessSession() {
?? return getSessionFactory().openStatelessSession();
}
/* (non-Javadoc)
* @see org.hibernate.SessionFactory#openStatelessSession(java.sql.Connection)
*/
public StatelessSession openStatelessSession(Connection connection) {
?? return getSessionFactory().openStatelessSession(connection);
}
/* (non-Javadoc)
* @see javax.naming.Referenceable#getReference()
*/
public Reference getReference() throws NamingException {
?? return getSessionFactory().getReference();
}
}
然后我用一个常量类来标识sessionFactory
public class DynamicDataSourceType {
public static final String A= "aSessionFactory";
public static final String B= "bSessionFactory";
public static final String C= "cSessionFactory";
}
最后一个关键类:用来存放当前正在使用的sessionFactory
public class CustomerContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setCustomerType(String customerType) {
?? Assert.notNull(customerType, "customerType cannot be null");
?? contextHolder.set(customerType);
}
public static String getCustomerType() {
?? return (String) contextHolder.get();
}
public static void clearCustomerType() {
?? contextHolder.remove();
}
}
可以在action、service、dao中进行数据库切换,切换方式:
CustomerContextHolder.setCustomerType(DynamicDataSourceType.A);
?
以上思路来自javaEye论坛的一个高手,在此标识感谢
?
?
?
?
?
?------------------------个人觉得此思路还是不错,如果能加分布务事务一并封装进去,是不是会更好一点?</name:>