最近写了一个多数据源的代码,结果在使用的过程中出现了在一个请求中(方法中)两个数据库交替使用的情况,最后情况是数据库切换不过来
并且在项目配置中有懒加载和OpenSessionInViewFilter
数据库一个为本地数据库一个为基金数据库
要做的事情就是在本地查询到基金代码接着再循环去基金库查询基金数据
中间报错为在本地数据库中查询不到某个表(其实是在基金库中)
controller层
@RequestMapping(value = "/fundsmatch")
public String fundsMatch(HttpServletRequest request, HttpServletResponse response){
BtnHitsCount hits = olService.findByBtnNameAndPage("匹配理财方案", "我的页面");
hits.setHits(hits.getHits()+1);
olService.saveHits(hits);
if (getAttributeFromSession(Constant.SESSION_KEY_CURRENTUSERID) == null) {
return "login";
}
String openuid = "c8572f0f-dca3-4b63-aecd-2f32d5510ba3";
Integer userId = (Integer)getAttributeFromSession(Constant.SESSION_KEY_CURRENTUSERID);
-------------------在本地库取数据--------------------
JoUser joUser = joUserService.find(userId);
PortfolioMatch match = portfolioMatchService.findEntity(userId+"");
List<FundsGroupBean> list = new ArrayList<FundsGroupBean>();
if(joUser.getRisklevel()!=null&&match!=null&&match.getPlanId()!=null){
ScoreStandard standard = scoreStandard.findEntity(match.getScoreId()+"");
FundPortfolio fundPortfolio = match.getFundPortfolioId();
String[] fundcodes = fundPortfolio.getFundcodes().split(",");
for (int i = 0; i < fundcodes.length; i++) {
FundsGroupBean fgb = new FundsGroupBean();
try {
--------------切换基金库取数据--------------
JSONObject json = JSONObject.fromObject(fundsNavService.findFundsInfo(fundcodes[i]));
--------------切换基金库取数据--------------
} catch (Exception e) {
e.printStackTrace();--------------在此报错--------------------
}
fgb.setFundCode(fundcodes[i]);
list.add(fgb);
}
request.setAttribute("list", list);
request.setAttribute("rates", fundPortfolio.getMinIncomeRate()+"~"+fundPortfolio.getMaxIncomeRate());
request.setAttribute("risktest", 1);
request.setAttribute("level", joUser.getRisklevel()+" "+standard.getName());
}else{
return "redirect:/questionnaire/plan_questionnaire";
}
return "fundsmatch";
}
基金server层内部代码
@Service
public class FundsNavServiceImpl implements FundsNavService {
@Autowired
FundsNavDao dao;
public Map<String, Object> findNav(String fundcode, String day) {
ContextHolder.setDbType(DBType.dataSource2);
Map<String,Object> map = dao.findNav(fundcode, day);
ContextHolder.clearDBType();
return map;
}
public Map<String, Object> findFundsInfo(String fundcode) {
ContextHolder.setDbType(DBType.dataSource2);
Map<String,Object> retMap = new HashMap<String,Object>();
retMap.put("fundinfo", dao.findFundsInfo(fundcode));
ContextHolder.clearDBType();
return retMap;
}
public Map<String, Object> searchFunds(String fundcode, String page,
String rows) {
ContextHolder.setDbType(DBType.dataSource2);
Map<String,Object> retMap = new HashMap<String,Object>();
retMap.put("fundList", dao.searchFunds(fundcode, page, rows));
ContextHolder.clearDBType();
return retMap;
}
}
数据源枚举类
package com.chy.dangaowm.util.fund;
public enum DBType {
dataSource1,
dataSource2
}
继承的AbstractRoutingDataSource类并且在spring中配置
package com.chy.dangaowm.util.fund;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
DBType dbType = ContextHolder.getDBType();
return dbType;
}
}
基金库切换类
package com.chy.dangaowm.util.fund;
public class ContextHolder {
private static final ThreadLocal<Object> holder = new ThreadLocal<Object>();
public static void setDbType(DBType dbType){
holder.set(dbType);
}
public static DBType getDBType(){
return (DBType)holder.get();
}
public static void clearDBType(){
holder.remove();
}
}
spring配置文件
<!-- 配置dataSource1 进行save,update操作时连接这个数据库-->
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.slave.url}" />
<property name="username" value="${jdbc.slave.username}" />
<property name="password" value="${jdbc.slave.password}" />
<property name="initialSize" value="${jdbc.initialSize}" />
<property name="maxActive" value="${jdbc.maxActive}" />
<property name="maxIdle" value="${jdbc.maxIdle}" />
<property name="minIdle" value="${jdbc.minIdle}" />
<property name="testOnBorrow" value="${jdbc.testOnBorrow}" />
<property name="testWhileIdle" value="${jdbc.testWhileIdle}" />
<property name="validationQuery" value="${jdbc.validationQuery}" />
<!-- <property name="validationQuery" value="select 1;" /> -->
</bean>
<!--配置dataSource1 进行select操作时连接这个数据库 -->
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.master.url}" />
<property name="username" value="${jdbc.master.username}" />
<property name="password" value="${jdbc.master.password}" />
<property name="initialSize" value="${jdbc.initialSize}" />
<property name="maxActive" value="${jdbc.maxActive}" />
<property name="maxIdle" value="${jdbc.maxIdle}" />
<property name="minIdle" value="${jdbc.minIdle}" />
<property name="testOnBorrow" value="${jdbc.testOnBorrow}" />
<property name="testWhileIdle" value="${jdbc.testWhileIdle}" />
<property name="validationQuery" value="${jdbc.validationQuery}" />
<!-- <property name="validationQuery" value="select 1;" /> -->
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource1" />
<!-- mysql 动态数据源设置-->
<bean id="mysqlDynamicDataSource" class="com.chy.dangaowm.util.fund.DynamicDataSource">
<property name="targetDataSources">
<!-- 标识符类型 -->
<map key-type="com.chy.dangaowm.util.fund.DBType">
<entry key="dataSource1" value-ref="dataSource1"/>
<entry key="dataSource2" value-ref="dataSource2"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource1"/>
</bean>
<!-- 配置sessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="mysqlDynamicDataSource" />
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
<property name="packagesToScan">
<array>
<value>com.chy.dangaowm.domain</value>
</array>
</property>
</bean>
<!-- 配置事务管理 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />