0 0

关于spring+hibernate配置多数据源的问题20

我的项目是个webservice项目,使用了hibernate+spring框架,由于项目中要用到两个数据库(都是oracle数据库),我在网上查了一些资料,但是在我的项目中做数据源切换的时候总是切换不过去,也就是说只能连接默认的数据源,一下是我的spring配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context-3.0.xsd"
	default-autowire="byName">

	<context:annotation-config />

	<!-- AXIS2通过该对象加载spring中的bean 固定配置 -->
	<bean id="applicationContext"
		class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
	<!-- end -->

	<!-- AXIS2本地业务配置 -->
	<bean id="PAPWebService" class="com.pap.ws.PAPWebService" />
	<!-- end -->

	<context:component-scan base-package="com.pap">
		<context:include-filter type="regex" expression=".dao.impl.*" />
		<context:include-filter type="regex" expression=".serviec.impl.*" />
		<context:include-filter type="regex" expression=".entity.*" />
	</context:component-scan>

	<bean id="tmsDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
		<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
		<property name="driverUrl" value="jdbc:oracle:thin:@172.17.30.80:1521:tms" />
		<property name="user" value="SELFSERVICE" />
		<property name="password" value="Password123" />
		<!-- 最大数据库连接数 -->
		<property name="maximumConnectionCount" value="100" />
		<!-- 最小数据库连接数 -->
		<property name="minimumConnectionCount" value="3" />
		<!-- 最少保持的空闲连接数(默认2个) -->
		<property name="prototypeCount" value="3" />
		<!-- 没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受 -->
		<!-- <property name="maximumNewConnections" value="20"/> -->
		<!-- 最大的并发连接数 -->
		<property name="simultaneousBuildThrottle" value="50" />
		<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒 -->
		<property name="houseKeepingSleepTime" value="10000" />
		<!-- 用于保持连接的测试语句 -->
		<property name="houseKeepingTestSql" value="select sysdate from dual" />
		<!-- 在使用之前测试 -->
		<property name="testBeforeUse" value="true" />
	</bean>

	<bean id="hisDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
		<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
		<property name="driverUrl" value="jdbc:oracle:thin:@172.17.1.252:1521:ORCL" />
		<property name="user" value="system" />
		<property name="password" value="aaaaaa" />
		<!-- 最大数据库连接数 -->
		<property name="maximumConnectionCount" value="100" />
		<!-- 最小数据库连接数 -->
		<property name="minimumConnectionCount" value="3" />
		<!-- 最少保持的空闲连接数(默认2个) -->
		<property name="prototypeCount" value="3" />
		<!-- 没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受 -->
		<!-- <property name="maximumNewConnections" value="20"/> -->
		<!-- 最大的并发连接数 -->
		<property name="simultaneousBuildThrottle" value="50" />
		<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒 -->
		<property name="houseKeepingSleepTime" value="10000" />
		<!-- 用于保持连接的测试语句 -->
		<property name="houseKeepingTestSql" value="select sysdate from dual" />
		<!-- 在使用之前测试 -->
		<property name="testBeforeUse" value="true" />
	</bean>

	<bean id="dynamicDataSource" class="com.pap.datasource.DynamicDataSource">
		<!-- 通过key-value的形式来关联数据源 -->
		<property name="targetDataSources">
			<map key-type="java.lang.String">
				<entry value-ref="tmsDataSource" key="tmsDataSource"></entry>
				<entry value-ref="hisDataSource" key="hisDataSource"></entry>
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="tmsDataSource">
		</property>
	</bean>

	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dynamicDataSource" />
		<property name="packagesToScan">
			<list>
				<value>com.pap.entity</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
				<!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->
			</props>
		</property>
	</bean>

	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<tx:annotation-driven transaction-manager="transactionManager" />

</beans>

下面是我写的两个用于切换数据源的类:

DataSourceContextHolder.java
package com.pap.datasource;

public class DataSourceContextHolder {
	public static final String DATA_SOURCE_TMS = "tmsDataSource";

	public static final String DATA_SOURCE_HIS = "hisDataSource";

	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

	public static void setDataSourceType(String customerType) {
		contextHolder.set(customerType);
	}

	public static String getDataSourceType() {
		return contextHolder.get();
	}

	public static void clearDataSourceType() {
		contextHolder.remove();
	}
}


DynamicDataSource.java
package com.pap.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

	@Override
	protected Object determineCurrentLookupKey() {
		return DataSourceContextHolder.getDataSourceType();
	}

}


dao层代码
package com.pap.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.pap.dao.BaseDao;

@Repository("baseDao")
public class BaseDaoImpl extends HibernateDaoSupport implements BaseDao{

	@Override
	public <T> Serializable save(T entity) throws Exception {
		Serializable s = this.getHibernateTemplate().save(entity);
		return s;
	}
	
	@Override
	public <T> void update(T entity) throws Exception {
		this.getHibernateTemplate().update(entity);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> query(String hql,Object[] values) throws Exception {
		return this.getHibernateTemplate().find(hql, values);
	}

	@Override
	public <T> List<T> query(String hql, Object value) throws Exception {
		return query(hql, new Object[]{value});
	}
	
	@Override
	public <T>T getEntity(Class<T> entityClass, Serializable id) throws Exception {
		return this.getHibernateTemplate().get(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> find(DetachedCriteria detachedCriteria, int firstResult, int maxResults) throws Exception {
		return getHibernateTemplate().findByCriteria(detachedCriteria, firstResult, maxResults);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public <T> List<T> find(DetachedCriteria criteria) throws Exception {
		return getHibernateTemplate().findByCriteria(criteria);
	}
}


service层代码,我是在这里做的数据源切换
package com.pap.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.pap.dao.BaseDao;
import com.pap.datasource.DataSourceContextHolder;
import com.pap.entity.ChargeTypeDict;
import com.pap.entity.ClinicForRegist;
import com.pap.entity.MedicalCard;
import com.pap.entity.Patient;
import com.pap.entity.SelfTerminal;
import com.pap.entity.TransactionRecord;
import com.pap.entity.User;
import com.pap.service.BaseService;

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class BaseServiceImpl implements BaseService {
	@Resource
	private BaseDao baseDao;


	/**
	 * 查询排号信息
	 */
	@Override
	public List<ClinicForRegist> queryClinicForRegist(java.sql.Date clinicDate, Object[] timeDesc, int firstResult, int maxResults) throws Exception {
		DataSourceContextHolder.setDataSourceType(DataSourceContextHolder.DATA_SOURCE_HIS);
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ClinicForRegist.class);
		detachedCriteria.add(Restrictions.eq("clinicDate", clinicDate));
		detachedCriteria.add(Restrictions.in("timeDesc", timeDesc));
		List<ClinicForRegist> list = baseDao.find(detachedCriteria, firstResult, maxResults);
		DataSourceContextHolder.clearDataSourceType();
		return list;
	}

}


webservice接口类
package com.pap.ws;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import com.pap.entity.ChargeTypeDict;
import com.pap.entity.ClinicForRegist;
import com.pap.entity.ClinicIndex;
import com.pap.entity.DeptDict;
import com.pap.entity.MedicalCard;
import com.pap.entity.Patient;
import com.pap.entity.Privileges;
import com.pap.entity.Response;
import com.pap.entity.SelfTerminal;
import com.pap.entity.TransactionRecord;
import com.pap.entity.User;
import com.pap.service.BaseService;
import com.pap.util.MD5Util;

public class PAPWebService {
	@Resource
	BaseService baseService;

	/**
	 * 查询可挂号信息
	 * @param firstResult 起始条数
	 * @param maxResults 最大条数
	 * @return
	 */
	public Response queryClinicRegist(int firstResult, int maxResults) {
		Response response = new Response();
		try {
			Calendar calendar = Calendar.getInstance();
			int hour = calendar.get(Calendar.HOUR_OF_DAY);
			String[] timeDesc = null;
			if (8 < hour && hour < 12) {
				timeDesc = new String[] { "白天", "上午", "下午", "昼夜" };
			} else if (hour > 11 && hour < 18) {
				timeDesc = new String[] { "白天", "下午", "昼夜" };
			} else {
				timeDesc = new String[] {"昼夜" };
			}
			List<ClinicForRegist> list = baseService.queryClinicForRegist(new java.sql.Date(calendar.getTimeInMillis()), timeDesc, firstResult, maxResults);
			if(list.size() > 0){
				response.setResult("S");
				response.setArrayData(list);
			}else{
				response.setResult("F");
				response.setResult("没有查询到记录");
			}
				
		} catch (Exception e) {
			e.printStackTrace();
			response.setResult("F");
			response.setErrorInfo(e.getMessage());
		}
		return response;
	}
	
	public void setClinicForRegist(ClinicForRegist clinicForRegist){
	}
	
	public void setClinicIndex(ClinicIndex clinicIndex){
	}
	
	public void setDeptDict(DeptDict deptDict){
	}
}

问题补充:我这个项目是axis2的webservice项目,下面是我的axis2的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<serviceGroup>
<service name="PAPWebService" scope="transportsession">
<Description>Please Type your service description here</Description>

<!-- messageReceivers是配置方法的返回值的,如果无返回值会取RPCInOnlyMessageReceiver,否则取RPCMessageReceiver -->
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</messageReceivers>
<!-- end -->

<!-- ServiceObjectSupplier是整合spring的必要配置 -->
<parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter>
<!-- end -->

<!-- applicationContext.xml中配置的实现类名称 -->
<parameter name="SpringBeanName">PAPWebService</parameter>
<!-- end -->

<!-- 实现类的接口 -->
<parameter name="ServiceClass" locked="false">com.pap.ws.PAPWebService</parameter>
<!-- end -->
</service>
</serviceGroup>

问题补充:经过我的测试发现,如果不涉及到AXIS2,那么数据源切换是没有问题的,但是加上AXIS2就会切换不过去,不知道是jar包冲突还是其他什么问题
2014年2月17日 20:44

4个答案 按时间排序 按投票排序

1 0

spring里面怎么配置了?如果两个库完全一致,最省事的方式还是在spring里面配置两个datasource,2个hibernatetemplate分别注入相应的datasource,把hibernatetemplate注入service,需要哪个库的时候调用哪个hibernatetemplate

2014年2月18日 10:30
0 0

如果把

 @Override  
    public List<ClinicForRegist> queryClinicForRegist(java.sql.Date clinicDate, Object[] timeDesc, int firstResult, int maxResults) throws Exception {  
        DataSourceContextHolder.setDataSourceType(DataSourceContextHolder.DATA_SOURCE_HIS);  
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ClinicForRegist.class);  
        detachedCriteria.add(Restrictions.eq("clinicDate", clinicDate));  
        detachedCriteria.add(Restrictions.in("timeDesc", timeDesc));  
        List<ClinicForRegist> list = baseDao.find(detachedCriteria, firstResult, maxResults);  
        DataSourceContextHolder.clearDataSourceType();  
        return list;  
    }  

改为
 @Override  
    public List<ClinicForRegist> queryClinicForRegist(java.sql.Date clinicDate, Object[] timeDesc, int firstResult, int maxResults) throws Exception {  
        DataSourceContextHolder.setDataSourceType("hisDataSource");  
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ClinicForRegist.class);  
        detachedCriteria.add(Restrictions.eq("clinicDate", clinicDate));  
        detachedCriteria.add(Restrictions.in("timeDesc", timeDesc));  
        List<ClinicForRegist> list = baseDao.find(detachedCriteria, firstResult, maxResults);  
        DataSourceContextHolder.clearDataSourceType();  
        return list;  
    }  

试试呢?看看是不是因为key获取不到对应的Datasource

2014年2月19日 18:06
0 0

proxool配置多数据源必须为每一个数据源bean配置属性alias,也就是取个别名,当然每个datasourse别名是不同的,那么该问题中的配置可为:
tmsDataSource
<property name="alias" value="proxool.tms" />
hisDataSource
<property name="alias" value="proxool.his" />

2014年2月19日 13:42
0 0

你可以调试看下每次这个方法是否是你自己设置的数据库名称
public static String getDataSourceType() { 
        return contextHolder.get(); 
   }

2014年2月18日 11:09

相关推荐

Global site tag (gtag.js) - Google Analytics