使用SpringBoot 配置Oracle和H2双数据源及问题

目录
  • 配置POM
  • 配置yml
  • 配置注入
  • 问题

在上节使用了H2之后感觉很爽,很轻便,正好有个项目要求简单,最好不适用外部数据库,于是就想着把H2数据库集成进来,这个系统已经存在了一个Oracle,正好练习下配置多数据源,而在配置多数据源时,H2的schema配置不生效真是花了我好长时间才解决。。。所以也记录一下

配置POM

<!-- oracle -->
 <dependency>
     <groupId>com.github.noraui</groupId>
     <artifactId>noraui</artifactId>
     <version>2.4.0</version>
 </dependency>
<!-- h2-->
 <dependency>
     <groupId>com.h2database</groupId>
     <artifactId>h2</artifactId>
     <version>1.4.197</version>
 </dependency>
 <!-- mybatisplus -->
 <dependency>
 	  <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.1.1</version>
 </dependency>

配置yml

spring:
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  datasource:
    driver-class-name: org.h2.Driver
    schema: classpath:h2/schema-h2.sql
    data: classpath:h2/data-h2.sql
    jdbc-url: jdbc:h2:file:D:/Cache/IdeaWorkSpace/BigData/CustomerModel/src/main/resources/h2/data/h2_data
    username: root
    password: a123456
    initialization-mode: always
    oracle:
     driver-class-name: oracle.jdbc.driver.OracleDriver
     jdbc-url: jdbc:oracle:thin:@xxx:1521:cmis
     username: xxx
     password: xxx
  h2:
    console:
      enabled: true
      path: /h2-console

可以看到配置中配置了两个数据源,主数据源是H2,第二个数据源是Oracle,接下来是通过配置类来注入数据源

配置注入

配置H2主数据源

package com.caxs.warn.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
 * @Author: TheBigBlue
 * @Description:
 * @Date: 2019/9/18
 */
@Configuration
@MapperScan(basePackages = "com.caxs.warn.mapper.h2", sqlSessionFactoryRef = "h2SqlSessionFactory")
public class H2DSConfig {
    @Bean(name = "h2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "h2TransactionManager")
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(this.dataSource());
    }
    @Bean(name = "h2SqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("h2DataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sessionFactory.getObject();
    }
    @Bean(name = "h2Template")
    public JdbcTemplate h2Template(@Qualifier("h2DataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

配置oracle从数据源

package com.caxs.warn.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
 * @Author: TheBigBlue
 * @Description:
 * @Date: 2019/9/18
 */
@Configuration
@MapperScan(basePackages = "com.caxs.warn.mapper.oracle",sqlSessionFactoryRef = "oracleSqlSessionFactory")
public class OracleDSConfig {
    @Bean(name = "oracleDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.oracle")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "oracleTransactionManager")
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(this.dataSource());
    }
    @Bean(name = "oracleSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("oracleDataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sessionFactory.getObject();
    }
    @Bean(name = "oracleTemplate")
    public JdbcTemplate oracleTemplate(@Qualifier("oracleDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

问题

Schema “classpath:h2/schema-h2.sql” not found

  

经过上面的配置就可以使用双数据源了,但是当我们测试时会发现报如下错误:Schema “classpath:h2/schema-h2.sql” not found,这个问题我也是找了好久,因为在配置但数据源的时候没有这个问题的,在配置多数据源才有了这个问题。

  

单数据源时,是直接SpringBoot自动配置DataSource的,这个时候是正常的,而当配置多数据源时,我们是通过@Configuration来配置数据源的,怀疑问题出在 DataSourceBuilder 创建数据源这个类上,而单数据源自动装载时不会出现这样的问题。然后百度搜了下这个DataSourceBuilder,看到文章中实例的配置中schema是这样写的:

package com.caxs.warn.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
 * @Author: TheBigBlue
 * @Description: 服务启动后,初始化数据库
 * @Date: 2019/9/19
 */
@Component
public class ApplicationRunnerService implements ApplicationRunner {
    private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRunnerService.class);
    @Autowired
    @Qualifier("h2Template")
    private JdbcTemplate h2Template;
    @Value("${invoke.schema.location}")
    private String schema;
    @Value("${invoke.data.location}")
    private String data;
    /**
     * @Author: TheBigBlue
     * @Description: 项目启动,执行sql文件初始化
     * @Date: 2019/9/19
     * @Param args:
     * @Return:
     **/
    @Override
    public void run(ApplicationArguments args) {
        String schemaContent = this.getFileContent(schema);
        String dataContent = this.getFileContent(data);
        h2Template.execute(schemaContent);
        h2Template.execute(dataContent);
    }
    /**
     * @Author: TheBigBlue
     * @Description: 获取classpath下sql文件内容
     * @Date: 2019/9/19
     * @Param filePath:
     * @Return:
     **/
    private String getFileContent(String filePath) {
        BufferedReader bufferedReader = null;
        String string;
        StringBuilder data = new StringBuilder();
        try {
            ClassPathResource classPathResource = new ClassPathResource(filePath);
            bufferedReader = new BufferedReader(new InputStreamReader(classPathResource.getInputStream()));
            while ((string = bufferedReader.readLine()) != null) {
                data.append(string);
            }
        } catch (IOException e) {
            LOGGER.error("加载ClassPath资源失败", e);
        }finally {
            if(null != bufferedReader){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return data.toString();
    }
}

  

抱着尝试的态度改了下,发现果然没问题了!!原来是在SpringBoot2.0之后schema对应的DataSourceProperties类中schema属性是一个List,所以需要前面加 - (yml中加-映射集合),记录下防止后面再踩坑。

Table “USER” not found; SQL statement:

  

这个问题也是在只有配置多数据源时才会碰到的问题,就是配置的spring.datasource.schema和spring.datasource.data无效。这个我看了下如果是配置单数据源,springboot自动加载Datasource,是没问题的,但是现在是我们自己维护的datasource: return DataSourceBuilder.create().build();所以感觉还是DataSourceBuilder在加载数据源的时候的问题,但是还是没有找到原因。有网友说必须加initialization-mode: ALWAYS这个配置,但是我配置后也是不能用的。

  

最后没办法就配置了一个类,在springboot启动后,自己加载文件,读取其中的sql内容,然后用jdbcTemplate去执行了下,模拟了下初始化的操作。。。后面如果有时间再来解决这个问题。

package com.caxs.warn.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
 * @Author: TheBigBlue
 * @Description: 服务启动后,初始化数据库
 * @Date: 2019/9/19
 */
@Component
public class ApplicationRunnerService implements ApplicationRunner {
    private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRunnerService.class);
    @Autowired
    @Qualifier("h2Template")
    private JdbcTemplate h2Template;
    @Value("${invoke.schema.location}")
    private String schema;
    @Value("${invoke.data.location}")
    private String data;
    /**
     * @Author: TheBigBlue
     * @Description: 项目启动,执行sql文件初始化
     * @Date: 2019/9/19
     * @Param args:
     * @Return:
     **/
    @Override
    public void run(ApplicationArguments args) {
        String schemaContent = this.getFileContent(schema);
        String dataContent = this.getFileContent(data);
        h2Template.execute(schemaContent);
        h2Template.execute(dataContent);
    }
    /**
     * @Author: TheBigBlue
     * @Description: 获取classpath下sql文件内容
     * @Date: 2019/9/19
     * @Param filePath:
     * @Return:
     **/
    private String getFileContent(String filePath) {
        BufferedReader bufferedReader = null;
        String string;
        StringBuilder data = new StringBuilder();
        try {
            ClassPathResource classPathResource = new ClassPathResource(filePath);
            bufferedReader = new BufferedReader(new InputStreamReader(classPathResource.getInputStream()));
            while ((string = bufferedReader.readLine()) != null) {
                data.append(string);
            }
        } catch (IOException e) {
            LOGGER.error("加载ClassPath资源失败", e);
        }finally {
            if(null != bufferedReader){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return data.toString();
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解决SpringBoot项目使用多线程处理任务时无法通过@Autowired注入bean问题

    最近在做一个"温湿度控制"的项目,项目要求通过用户设定的温湿度数值和实时采集到的数值进行比对分析,因为数据的对比与分析是一个通过前端页面控制的定时任务,经理要求在用户开启定时任务时,单独开启一个线程进行数据的对比分析,并将采集到的温湿度数值存入数据库中的历史数据表,按照我们正常的逻辑应该是用户在请求开启定时任务时,前端页面通过调用后端接口,创建一个新的线程来执行定时任务,然后在线程类中使用 @Autowired 注解注入保存历史数据的service层,在线程类中调用service层保存

  • 解决SpringBoot 测试类无法自动注入@Autowired的问题

    原来的测试类的注解: @RunWith(SpringRunner.class) @SpringBootTest 一直没法自动注入,后来在@SpringBootTest, 加入启动类Application后就可以了 @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) 补充:spring boot项目单元测试时,@Autowired无法注入Service解决方式 首先确认: 测试类所在包名要和启动类一致

  • springboot使用@value注入配置失败的解决

    目录 springboot使用@value注入配置文件失败 问题解决方向一 问题解决方向二 @Value注入失败,注入值为null的问题 大概就是下面这样 结果不知道为什么,@Value注入一直为空?? 原因如下 解决办法 springboot使用@value注入配置文件失败 遇到的问题原因是:类中注入对象不能用static. 问题解决方向一 1.改为如图示,去掉static 问题解决方向二 1.仍然定义静态变量,但在其set方法上使用@Value进行赋值 2.仍然定义静态变量,同时定义一个普通

  • 详解SpringBoot 多线程处理任务 无法@Autowired注入bean问题解决

    在多线程处理问题时,无法通过@Autowired注入bean,报空指针异常, 在线程中为了线程安全,是防注入的,如果要用到这个类,只能从bean工厂里拿个实例. 解决方法如下: 1.创建一个工具类代码: package com.hqgd.pms.common; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.spri

  • 使用SpringBoot 配置Oracle和H2双数据源及问题

    目录 配置POM 配置yml 配置注入 问题 在上节使用了H2之后感觉很爽,很轻便,正好有个项目要求简单,最好不适用外部数据库,于是就想着把H2数据库集成进来,这个系统已经存在了一个Oracle,正好练习下配置多数据源,而在配置多数据源时,H2的schema配置不生效真是花了我好长时间才解决...所以也记录一下 配置POM <!-- oracle --> <dependency> <groupId>com.github.noraui</groupId> &l

  • SpringBoot配置web访问H2的方法

    [前情提要]最近开始搭建博客,在本地调试的时候使用的数据库是h2,但是调试的时候需要查看数据库,本文也由此而来. 下面是我用到的方法: 使用IDEA的Database连接工具,具体操作方法就是按照要求配置连接url,用户名和密码即可.具体操作见下图: 查询结果: 但是但是这个时候启动项目会报错: org.h2.jdbc.JdbcSQLException: Database may be already in use: null. Possible solutions: close all oth

  • springboot + JPA 配置双数据源实战

    目录 springboot + JPA 配置双数据源 1.首先配置application.yml文件设置主从数据库 2.使用配置类读取application.yml配置的两个数据源 3.然后通过类的方式配置两个数据源 4.启动类主函数入口 springboot + JPA 配置双数据源 1.首先配置application.yml文件设置主从数据库 spring: servlet: multipart: max-file-size: 20MB max-request-size: 20MB prof

  • SpringBoot+Jpa项目配置双数据源的实现

    目录 引言 配置yml文件 创建数据源配置类 为每个数据库创建配置类 引言 今天为大家带来一些非常有用的实战技巧,比如在我们需要对两个数据库进行操作的时候而哦我们通常用的只是单数据库查询,这就触及到知识盲点了,那么废话不多说上代码! 配置yml文件 server: port: 8080 spring: profiles: active: dev jackson: time-zone: GMT+8 # 这里是我们的数据库配置地方 datasource: data1: #这里是数据库一 driver

  • 使用springboot+druid双数据源动态配置操作

    目录 一.yml配置 二.动态切换数据源配置文件 1.数据源db1 2.数据源db2 三.多数据源的mapper包最好是分开 四.代码中调用 总结 进行动态切换,需要在类里面配置,顺便解决mybatis-plus自带代码无法使用问题,直接上代码: 一.yml配置 数据源可以都是oracle的也可以一个是oracle一个是mysql的. spring: datasource: druid: db-type: com.alibaba.druid.pool.DruidDataSource #多数据源1

  • springboot配置内存数据库H2教程详解

    业务背景:因soa系统要供外网访问,处于安全考虑用springboot做了个前置模块,用来转发外网调用的请求和soa返回的应答.其中外网的请求接口地址在DB2数据库中对应专门的一张表来维护,要是springboot直接访问数据库,还要专门申请权限等,比较麻烦,而一张表用内置的H2数据库维护也比较简单,就可以作为替代的办法. 环境:springboot+maven3.3+jdk1.7 1.springboot的Maven工程结构 说明一下,resource下的templates文件夹没啥用.我忘记

  • Spring MVC配置双数据源实现一个java项目同时连接两个数据库的方法

    前言 本文主要介绍的是关于Spring MVC配置双数据源实现一个java项目同时连接两个数据库的方法,分享出来供大家参考学习,下面来看看详细的介绍: 实现方法: 数据源在配置文件中的配置 <pre name="code" class="java"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.spring

  • springboot配置多数据源的实例(MongoDB主从)

    相信看过上一篇文章的小伙伴已经知道了, 这章要讲的就是MongoDB主从配置. 在这边文章中,你将要学到的是在项目中配置主从数据库,并且兼容其他数据库哟..这些都是博主项目中需要并且比较重要的知识哦~ 好了,废话不多说,直接进主题. 1.pom依赖 <span style="white-space:pre"> </span><dependency> <groupId>org.springframework.boot</groupId

  • springboot v2.0.3版本多数据源配置方法

    本篇分享的是springboot多数据源配置,在从springboot v1.5版本升级到v2.0.3时,发现之前写的多数据源的方式不可用了,捕获错误信息如: 异常:jdbcUrl is required with driverClassName. 先来说下之前的多数据源配置如: spring: datasource: url: jdbc:sqlserver://192.168.122.111;DatabaseName=flight username: sa password: 1234.abc

  • springboot 配置DRUID数据源的方法实例分析

    本文实例讲述了springboot 配置DRUID数据源的方法.分享给大家供大家参考,具体如下: druid 是阿里开源的数据库连接池. 开发时整合 druid 数据源过程. 1.修改pom.xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> &l

随机推荐