频道栏目
首页 > 程序开发 > 软件开发 > 其他 > 正文
spring动态加载数据源
2017-02-17 09:24:04         来源:mingover的专栏  
收藏   我要投稿

spring动态加载数据源:前段时间有个项目,spring+hibernate 的框架,这个项目是数据库传输相关的,会配置好几个数据库,就考虑能否把数据库配置放在 一个表里,程序启动时加载,这样会减少配置文件,清晰明了。

简介

如果你的工程要操作多个数据库,而且都要集成到spring中,用spring 的配置文件配置是很常见的。配置多个xml然后import到主xml(applicationContext.xml),里面把datasource 和beanfactory ,扫描包等配置好即可,

不过动态加的话,就有所不同了。当然是先 百度/google一下了,发现有不少案例是 多数据源+动态切换,不过这和我们的程序还是有出入的.后来找到一个 动态加bean 的,类似:

DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) appContext.getBeanFactory();
        BeanDefinitionBuilder dataSourceBuider = BeanDefinitionBuilder.genericBeanDefinition(ComboPooledDataSource.class);

有了这个ioc的入口,那就简单些了,至少在定义bean方面是没问题的。

代码

文件一,beans.xml

文件二,ThirdImplTest.java (启动spring动态加载数据源)

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class ThirdImplTest {

    static Logger log = Logger.getLogger(TgdUserServiceThirdImplTest.class);

    TgdUserServiceThirdImpl impl ;

    @Before
    public void beforeS() {
        ConfigurableApplicationContext  appContext = new ClassPathXmlApplicationContext("classpath:beans.xml");
        appContext = (ConfigurableApplicationContext) tooper(appContext);
        impl = (TgdUserServiceThirdImpl)appContext.getBean("tgdUserServiceThirdImpl");

    }

    /**
     * 操作 代码注入
     * @param dbf
     * @param appContext
     */
    private ApplicationContext   tooper(ConfigurableApplicationContext  appContext){

        String driverClass = "com.mysql.jdbc.Driver";
        String jdbcUrl = "jdbc:mysql://192.168.1.1:3306/xxx?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&pinGlobalTxToPhysicalConnection=true&autoReconnect=true&useOldAliasMetadataBehavior=true";
        String user = "root";
        String password = "xxxx";

        DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) appContext.getBeanFactory();
        BeanDefinitionBuilder dataSourceBuider = BeanDefinitionBuilder .genericBeanDefinition(ComboPooledDataSource.class);  
        dataSourceBuider.addPropertyValue("driverClass", driverClass);  
        dataSourceBuider.addPropertyValue("jdbcUrl", jdbcUrl);
        dataSourceBuider.addPropertyValue("user",user);
        dataSourceBuider.addPropertyValue("password",password);
        dataSourceBuider.addPropertyValue("acquireIncrement","5");
        dataSourceBuider.addPropertyValue("initialPoolSize","3");
        dataSourceBuider.addPropertyValue("minPoolSize","3");
        dataSourceBuider.addPropertyValue("maxPoolSize","10");
        dataSourceBuider.addPropertyValue("maxIdleTime","600");
        dataSourceBuider.addPropertyValue("idleConnectionTestPeriod","3600");
        dataSourceBuider.addPropertyValue("maxStatements","100");
        dataSourceBuider.addPropertyValue("numHelperThreads","10");
        dataSourceBuider.addPropertyValue("testConnectionOnCheckout",false);
        dataSourceBuider.addPropertyValue("preferredTestQuery","SELECT 1 FROM DUAL");
        dataSourceBuider.addPropertyValue("breakAfterAcquireFailure",false);
        dataSourceBuider.addPropertyValue("acquireRetryAttempts",30);
        dbf.registerBeanDefinition("third_dataSource", dataSourceBuider.getBeanDefinition());

        // 配置 LocalSessionFactoryBean
        //LocalSessionFactoryBean注册,注册时候在获取结果不再是它本身而是sessionFactory  
        BeanDefinitionBuilder llfb = BeanDefinitionBuilder .genericBeanDefinition(LocalSessionFactoryBean.class);  
        //这里的属性对应配置文件或者LocalSessionFactoryBean源码中的属性来,自己去看看就晓得  
        llfb.addPropertyValue("dataSource", (DataSource)appContext.getBean("third_dataSource"));  
        List packagesToScanList = new ArrayList();
        packagesToScanList.add("com.snm.third");
        llfb.addPropertyValue("packagesToScan", packagesToScanList);

        Properties p = new Properties();
        p.setProperty("hibernate.hbm2ddl.auto","none");
        p.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect");
        p.setProperty("hibernate.show_sql","true");
        p.setProperty("hibernate.form_sql","true");
        p.setProperty("hibernate.connection.username",user);
        p.setProperty("hibernate.connection.password",password);
        p.setProperty("hibernate.connection.url",jdbcUrl);
        p.setProperty("hibernate.default_batch_fetch_size","30");
        p.setProperty("hibernate.cache.use_second_level_cache","false");
        p.setProperty("hibernate.current_session_context_class","org.springframework.orm.hibernate4.SpringSessionContext");
//        p.setProperty("hibernate.current_session_context_class","thread");


        llfb.addPropertyValue("hibernateProperties",p);
        dbf.registerBeanDefinition("third_sessionFactory", llfb.getBeanDefinition()); 



//        本来想看看集成spring 事务怎么搞的, 不过搞不定,这几行貌似没什么用
     // construct an appropriate transaction manager 
//        DataSourceTransactionManager txManager = new DataSourceTransactionManager((DataSource)appContext.getBean("third_dataSource"));
//        // configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methods
//        AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); 


        AnnotationConfigApplicationContext  annotationConfigApplicationContext = 
                new AnnotationConfigApplicationContext();

        annotationConfigApplicationContext.setParent(appContext);
        annotationConfigApplicationContext.scan("com.xxx.xxx");
        annotationConfigApplicationContext.refresh();
        return annotationConfigApplicationContext;
    }

    @Test
    public void testgetAllList() throws Exception {
        log.info(DJsonUtil.getJsonFromObect(impl.getAllList1(new HashMap(), null)));
    }
}

文件三 TUserServiceThirdImpl

import java.util.List;
import java.util.Map;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.apache.util.Sort;
import com.snm.third.model.equpt.TgdUser;


@Service
public class TUserServiceThirdImpl{

    @Autowired
    private SessionFactory sessionFactory;

    public List getAllList1(Map params, Sort sorts) {
        Session session = null;
        List list = null;
        try {
            session = sessionFactory.openSession();
            SQLQuery query = session.createSQLQuery("select * from tuser");
            list = query.list();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.close();
        }
        return list;
    }
}

上面三个文件,即可以使用了.

其它

在web中使用
在加载sping 时自己创建个类来继承sping的listen,重写
public void contextInitialized(ServletContextEvent event) 即可
public class SpringListener extends ContextLoaderListener{

    private static ApplicationContext context ;

    public static ApplicationContext getContext(){
        return context;
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.print("init spring================");
        super.contextInitialized(event);
        WebApplicationContext w = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
        context = tooper((ConfigurableApplicationContext) w); //这里加载
    }

问题

自动事务问题
不知道spring的aop怎么配置,即这行不知道怎么配置。

所以@Transactional 的使用暂时还没有。。如果要多数据源的事务,只能 begin后rollback

数据源的相互引用
平时使用spring的bean,都是直接@Resource,@Autowire 引进来,但多数据源的相互引用不行,数据源是一个个加载的,如果加A的过程中,有B的Autowire,则会依赖报错 。

spring cloud ?
貌似有spring搭建配置中心 的说法,不过还没了解过。

点击复制链接 与好友分享!回本站首页
上一篇:构建器的初始化
下一篇:matlab的多项式基础
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站