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 额,正在冲刺,请不要档我~~~~(>_<)~~~~
2 年多之前 回复
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币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
springmvc+mybatis 配置多数据源相互切换
近日因为项目需求,需要进行多数据源的切换,
Spring动态切换多数据源解决方案
Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性。而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据。        Spring2.x以后的版本中采用Proxy模式,就是我们在方案中实现一个虚拟的数据源,并且用它来
spring+hibernate多数据源切换のSessionFactory切换
看到好多多数据源的例子,有切换datasource的,有切换sessionFactory的,我的是mysql和sqlserver两个数据库之间的切换,涉及到方言,所以就采用了后者。因为之前差点成功了,但是由于疏忽犯了个脑残失误就卡在somewhe了 ,今天本来想理清一下思路问大神的,结果理了一下,自己搞定了。不废话了,直接进入正题。 首先说配置方面,正常情况下都是陪一个datasource,一个
spring动态创建切换多数据源问题分析与解决办法
Spring 在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在spring和hibernate框架中总是配置一个数据源,因而sessionFactory的dataSource属性总是指向这个数据源并且恒定不变,所有DAO在使用sessionFactory的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我
springMVC中多数据源切换的两种主流实现方法(一)
说到多数据源,使用的场景一般有:1,主从数据库切换;2,多租户间数据逻辑隔离;本文后继的例子均以SSM架构为基础讲解,如你的框架不适合,请参考思路即可。最关键的是org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource类。-------------------------------------------------
利用AbstractRoutingDataSource实现动态数据源切换 (一、Spring+Hibernate)
一、开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能。所以在出来数据库方言的时候基本上没有什么问题,但唯一可能出现问题的就是在hibernate做添加操作生成主键策略的时候。因为我们都知道hibernate的数据库本地方言会针对不同的数据库采用不同的主键生成策略。 所以针对
spring+mybatis 多数据源切换失败的可能原因。
spring+mybatis 多数据源切换失败的可能原因。 可能因为,加了事务。 // @Transactional(readOnly = false) // 需要事务操作必须加入此注解 就因为加了事务,导致了,问题的出现。 害得我把spring的框架都改写了,不过由于过于暴力,所以没写。 重新折回去看看了代码。
springMvc-Mybatis 实现主从数据库/多数据源切换配置
一、配置文件 1、spring-mybatis.xml master_driverUrl=jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true master_user
使用spring 实现真正多数据源的动态加载及动态切换
内容提示:数据的统计分析操作,项目是以spring为基础框架搭建的.收集现在网上的所有关于多数据源配置的方式,并没有自己十分满意的,例如我有N个数据源,按照现网可以搜索到的配置方式,都是在spring配置文件中配置N个datasource,并通过实现AbstractRoutingDataSource抽象类的子类进行多... 1 前言:   公司需要做一个分析统计系统,该系统需要连接N台服务器结
SpringMVC动态切换多个数据源解决方案(自测可用)
SpringMVC动态切换多个数据源解决方案 1.数据源配置 &amp;lt;!-- 事务 --&amp;gt; &amp;lt;bean id=&quot;transactionManager&quot; class=&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;&amp;gt; &amp;lt;propert...