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。
我的这个类是通过声明式事务包含在原来的事务中,我用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)的实现。