小工具      在线工具  汉语词典  css  js  c++  java

Spring动态加载数据源

java,java-spring,mysql,hibernate,spring 额外说明

收录于:40天前

前段时间,我有一个项目,一个spring+hibernate框架。该项目涉及数据库传输,需要配置多个数据库。我考虑过是否可以将数据库配置放在一个表中并在程序启动时加载。这将减少配置文件的数量。清清楚楚。

介绍

如果你的项目操作多个数据库并且全部集成到spring中,那么使用spring配置文件是很常见的。配置多个xml,然后导入到主xml(applicationContext.xml)中,这里配置了datasource、beanfactory、扫描包等。

但如果动态添加的话,那就不一样了。当然,我首先搜索了百度/谷歌,发现有很多多数据源+动态切换的情况,但这和我们的程序还是有区别的。后来发现了动态添加bean的方法,类似:

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

有了这个ioc入口,那就简单多了,至少定义bean不会有问题。

代码

文件1,beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">



</beans>

文件2、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<String> 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<String, String> 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怎么配置,即这行不知道怎么配置。
<tx:annotation-driven transaction-manager="transactionManager" />

所以@Transactional的使用还不能使用。 。如果您想要一个具有多个数据源的事务,则只能在开始后回滚。

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

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

. . .

相关推荐

额外说明

SpringMVC组件分析

SpringMVC组件解析 前端控制器:DispatcherServlet 用户请求到达前端控制器,它就相当于 MVC 模式中的 Controller,DispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,Dispat

额外说明

Spring之Spring案例分析

Spring案例分析 Spring案例分析 摘要 引言 词汇解释 详细介绍 不同领域的案例分析 实战项目示例 注意事项 总结 参考资料 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客-- 《java 面试题大全》 -惟余

额外说明

QPS、TPS、并发用户数、吞吐量

1、QPS QPSQueries Per Second 是每秒查询率 ,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准, 即每秒的响应请求数,也即是最大吞吐能力。 2、TPS TPS Transactio

额外说明

实战篇:SUSE 15 SP3 安装 Oracle 19C RAC 数据库

前言 这两天看到交流群里有朋友咨询 SUSE 15 SP3 安装 Oracle 19C RAC 遇到点问题,趁着周末有时间,抱着学习的心态,研究了一下如何安装,接下来就分享一下从零开始部署的流程! 总体来说,和 RHEL 部署流程上大同小异,主要是有一些

额外说明

计算机专业保研面试备考:计算机网络(临阵磨枪)

本文总结了计算机专业保研面试中的一些计网题目,也是博主当年的备考材料。由于博主的专业选择原因,并没有在这一科目上下太多功夫,本文仅适合临阵磨枪,不适合系统复习。 OSI参考模型 物理层、链路层、网络层、传输层、会话层、表示层和应用层 ALOHA协议:随机

额外说明

【Rust 基础篇】Rust Trait 对象:灵活抽象与动态分发

文章目录 导言 什么是 Trait 对象? 为什么需要 Trait 对象? Trait 对象的定义和使用 定义 Trait 实现 Trait 使用 Trait 对象 Trait 对象与泛型的区别 Trait 对象的使用场景 使用注意事项 示例:图形绘制

额外说明

阿里云实例迁移导致的ecstore不能再次访问的注意事项

ecstore是需要付费的,所以只有取得授权的产品才能够正常使用。授权的过程需要获取授权文件。获取授权文件的时候需要用ecstore自带的工具类生成对应的机器码,切换到hardware.sh的上一级目录。使用如下命令生成机器码。 /usr/local/w

额外说明

解决IDEA使用Spring Initializr创建项目时无法连接到https://start.spring.io的问题

IDEA使用Spring Initializr创建项目时报错: 但在浏览器中可访问: 如果配置完之后还是不能使用,就直接在网页上创建,然后导入配置idea即可。 启动.spring.io网页太慢了,使用启动.springboot.io访问: 选好之后创建

额外说明

mac os版本Intellij IDEA 搭建spring mvc的maven工程(新手教学)

转载自:https://blog.csdn.net/huapenguag/article/details/79462436 由于mac os和IDEA刚刚开始使用,所以专门写了一篇博客来记录一下使用IDEA搭建springMVC的maven项目。 1.打

ads via 小工具