2 qq 18538601 qq_18538601 于 2016.03.30 17:42 提问

多数据源springmvc+hibernate 切换问题 在一次请求中多次切换不成功

最近写了一个多数据源的代码,结果在使用的过程中出现了在一个请求中(方法中)两个数据库交替使用的情况,最后情况是数据库切换不过来
并且在项目配置中有懒加载和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" />

6个回答

CSDNXIAON
CSDNXIAON   2016.03.30 17:52

Java之——SpringMVC+MyBitis+多数据源切换
----------------------同志你好,我是CSDN问答机器人小N,奉组织之命为你提供参考答案,编程尚未成功,同志仍需努力!

qq_18538601
qq_18538601 额,正在冲刺,请不要档我~~~~(>_<)~~~~
一年多之前 回复
qq_18538601
qq_18538601   2016.03.31 09:32

没有人吗?这个问题不是问题吗?

qq_18538601
qq_18538601   2016.03.31 09:33

我要顶上去,我要顶上去,我要顶上去,够数了

penger7
penger7   2016.07.07 15:12

是否配置了事务? 如果配置了事务,先把事务关闭,再试试。

u013147600
u013147600   2016.09.13 21:37

解决了吗?我也遇到这种情况 dataSourceType切换过来了 但是访问还是报错了

spring3306
spring3306   2017.04.13 12:15

请问楼主问题解决了吗?

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!