spring依赖注入失效的原因之一

最近在做一个数据中心的一个项目,需要查询多个数据库,目前项目中有3个解决办法:

1.用hibernate的动态多数据源(通过方法参数选择使用哪个dataSource,然后注入sessionFactory,再注入transactionManager)

2.用mybatis去连接另外一个数据库

3.用springJDBC


我的功能只要查询而已,不需要事务,所以我选的是最简单的方法,就是在配置文件新建一个sessionFactory(死方法,不是hibernate的动态多数据源)。

    <bean id="sessionFactoryDC"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dcenter"/>
        <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">${hibernate.format_sql}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>

                <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
                <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
                <prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</prop>

                <prop key="hibernate.jdbc.batch_size">0</prop>

                <!--<prop key="hibernate.use_nationalized_character_data">false</prop>-->
                <prop key="hibernate.search.default.indexBase">${hibernate.search.default.indexBase}</prop>
            </props>
        </property>
    </bean>

dcenter是远程的一个数据源,然后我在程序里用Spring @Resource或者@Autowired@Qualifier的注解注入

	@Autowired
	public void setSessionFactory(@Qualifier("<span style="font-family: Arial, Helvetica, sans-serif;">sessionFactoryDC</span><span style="font-family: Arial, Helvetica, sans-serif;">")</span><span style="font-family: Arial, Helvetica, sans-serif;">final SessionFactory sessionFactory) {</span>
		custDao = new HibernateDao<Map, String>(sessionFactory, Map.class);
	}
发现注入的还是原来的数据源。研究一下,发现内部还有个方法,手动取得新的sessionFactory的bean 去调用createSQLQuery修改后成了这个样

	@Autowired
	public void setSessionFactory(final SessionFactory sessionFactory) {
		custDao = new HibernateDao<Map, String>(sessionFactory, Map.class) {
			@Override
			public SQLQuery createSqlQuery(String sql, Parameter parameter) {
				SessionFactory sf = (SessionFactory)SpringContextHolder.getBean("sessionFactoryDC");
				SQLQuery query = sf.getCurrentSession().createSQLQuery(sql);
				setParameter(query, parameter);
				return query;
			}
	
		};
	}


发现还是用的是原来的数据源,咋回事呢,研究发现getCurrentSession 与 openSession() 的区别

 1. openSession 从字面上可以看得出来,是打开一个新的session对象,而且每次使用都是打开一个新的session,假如连续使用多次,则获得的session不是同一个对象,并且使用完需要调用close方法关闭session。

  2. getCurrentSession ,从字面上可以看得出来,是获取当前上下文一个session对象,当第一次使用此方法时,会自动产生一个session对象,并且连续使用多次时,得到的session都是同一个对象,这就是与openSession的区别之一,简单而言,getCurrentSession 就是:如果有已经使用的,用旧的,如果没有,建新的。


我的这个类是通过声明式事务包含在原来的事务中,我用getCurrentSession取的是事务里面的sessionfactory,所有一直用的是原来的数据源。修改了一下:

	@Autowired
	public void setSessionFactory(final SessionFactory sessionFactory) {
		custDao = new HibernateDao<Map, String>(sessionFactory, Map.class) {
			@Override
			public SQLQuery createSqlQuery(String sql, Parameter parameter) {
				SessionFactory sf = (SessionFactory)SpringContextHolder.getBean("sessionFactoryDC");
				SQLQuery query = sf.openSession().createSQLQuery(sql);
                                sf.close();
				setParameter(query, parameter);
				return query;
			}
	
		};
	}

使用 openSession()后发现得到的是正确的数据源了。 注意:一定要记得关闭session,不然数据库连接会耗尽。


因为我这个功能不需要事务,所以我用的是简单的写死的新建一个sessionFactory,大家需要事务的话可以用动态创建sessionFactory的方法

http://fangang.iteye.com/blog/72486 这个有详细的说明。


强烈建议如果用hibernate实现多数据源的话要使用动态数据源(多一个负责判断选择数据源的bean+可以自己写一个自定义注解@dataSource)的实现。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值