温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

在SpringBoot应用程序中使用多个数据源的示例分析

发布时间:2022-02-25 15:08:32 来源:亿速云 阅读:122 作者:小新 栏目:开发技术

小编给大家分享一下在SpringBoot应用程序中使用多个数据源的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

属性文件

首先,让我们在 application.properties 文件中定义两个不同的数据源设置,如下所示:

server.port=9090
spring.output.ansi.enabled=ALWAYS

application-description=@project.description@
application-version=@project.version@

spring.customerdatasource.url=[url1]
spring.customerdatasource.username=[username1]
spring.customerdatasource.password=[password1]
spring.customerdatasource.driverClassName=oracle.jdbc.OracleDriver

spring.billingdatasource.url=[url2]
spring.billingdatasource.username=[username2]
spring.billingdatasource.password=[password1]
spring.billingdatasource.driverClassName=oracle.jdbc.OracleDriver

database.sql.databasename=SELECT dbid, name FROM v$database

正如我之前提到的,我使用过 Oracle 数据库,但你也可以使用其他数据库,只要相应地更改 driverClassName

数据源配置

为了创建 DataSource bean,我创建了一个 DatasourceConfig 类并将其注释为配置,并将两个数据源添加为两个不同的 bean

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

@Configuration
public class DatasourceConfig {

	Environment env;
	
	public DatasourceConfig(Environment env) {
		this.env = env;
	}

	@Bean(name = "customerDataSource")
    public DataSource customerDataSource() {
    	DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.customerdatasource.driverClassName"));
        dataSource.setUrl(env.getProperty("spring.customerdatasource.url"));
        dataSource.setUsername(env.getProperty("spring.customerdatasource.username"));
        dataSource.setPassword(env.getProperty("spring.customerdatasource.password"));

        return dataSource;
    }

    @Bean(name = "billingDataSource")
    public DataSource billingDataSource() {
    	DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.billingdatasource.driverClassName"));
        dataSource.setUrl(env.getProperty("spring.billingdatasource.url"));
        dataSource.setUsername(env.getProperty("spring.billingdatasource.username"));
        dataSource.setPassword(env.getProperty("spring.billingdatasource.password"));

        return dataSource;
    }
    
}

数据访问

我使用了 JdbcTemplate作为数据访问。要创建 DAO 接口,请在 com.tech.multipledatasources.dao 包下添加 IDatabaseDAO 接口,如下所示:

import com.tech.multipledatasources.domain.DatabaseInfo;

public interface IDatabaseDAO {
    
    public DatabaseInfo getDatabaseInfo();
}

我对这个接口做了两种不同的实现,因为即使它是一个简单的应用程序,现实生活中的场景也会有所不同。

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.tech.multipledatasources.domain.DatabaseInfo;

@Repository
public class BillingDAO implements IDatabaseDAO{
    
    private JdbcTemplate jdbcTemplate;
    
    @Value("${database.sql.databasename}")
    private String sql;

    public BillingDAO(@Qualifier("billingDataSource")DataSource datasource) {
        jdbcTemplate = new JdbcTemplate(datasource);
    }

    @Override
    public DatabaseInfo getDatabaseInfo() {
        return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<DatabaseInfo>(DatabaseInfo.class));
    }
}
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.tech.multipledatasources.domain.DatabaseInfo;

@Repository
public class CustomerDAO implements IDatabaseDAO {

    private JdbcTemplate jdbcTemplate;
    
    @Value("${database.sql.databasename}")
    private String sql;

    public CustomerDAO(@Qualifier("customerDataSource") DataSource datasource) {
        jdbcTemplate = new JdbcTemplate(datasource);
    }

    @Override
    public DatabaseInfo getDatabaseInfo() {
        return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<DatabaseInfo>(DatabaseInfo.class));
    }
}

对于 database.sql.databasename 变量,请在 application.properties 文件中添加“SELECT dbid, name FROM v$database”值。请注意,此 SQL 也适用于 Oracle 数据库。如果您打算使用不同的数据库,则需要更改此语句。

我使用构造函数级别的依赖注入来注入数据源,并使用 Qualifier 注释来指定 bean 名称。

我还使用 DatabaseInfo 模型类将 SQL 结果映射到一个对象中。

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class DatabaseInfo {

    private long dbid;
    private String name;
    
}

为了保持代码干净整洁,我使用了Lombok插件。

服务

我添加了两个服务类作为服务层,如下所示,注释为服务,并注入相关的DAO类:

import com.tech.multipledatasources.dao.BillingDAO;
import com.tech.multipledatasources.domain.DatabaseInfo;
import org.springframework.stereotype.Service;

@Service
public class BillingService {
    
    private BillingDAO billingDAO;

    public BillingService(BillingDAO billingDAO){
        this.billingDAO = billingDAO;
    }

    public DatabaseInfo getDatabaseInfo(){
        return billingDAO.getDatabaseInfo();
    }
}
import com.tech.multipledatasources.dao.CustomerDAO;
import com.tech.multipledatasources.domain.DatabaseInfo;
import org.springframework.stereotype.Service;

@Service
public class CustomerService {
    
    private CustomerDAO customerDAO;

    public CustomerService(CustomerDAO customerDAO){
        this.customerDAO = customerDAO;
    }

    public DatabaseInfo getDatabaseInfo(){
        return customerDAO.getDatabaseInfo();
    }
}

异常处理

我在下面创建了 CustomException 类,并在 ControllerAdvice 中使用了中央异常处理:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import java.util.Date;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CustomException extends Exception {
    
    private static final long serialVersionUID = 1L;
	private int errStatusCode;
    private String errMsg;
    private Date errDate;
    private String reqDesc; 
}
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;

import java.util.Date;

public class ControllerExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<CustomException> genericExceptionHandler(Exception ex, WebRequest request) {
        CustomException customException = new CustomException(
            HttpStatus.EXPECTATION_FAILED.value(),
            ex.getMessage(),
            new Date(),
            request.getDescription(false)
            );
        
        return new ResponseEntity<CustomException>(customException, HttpStatus.EXPECTATION_FAILED);
      }
}

控制器

我创建了两个控制器。一种用于计费,一种用于客户请求;将两个服务类注入控制器。

import com.tech.multipledatasources.domain.DatabaseInfo;
import com.tech.multipledatasources.service.BillingService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/billing")
public class BillingController {
    
    private BillingService billingService;

    public BillingController(BillingService billingService){
        this.billingService = billingService;
    }

    @GetMapping("/dsinfo")
    public ResponseEntity<DatabaseInfo> getDatasourceInfo(){
        return ResponseEntity.ok(billingService.getDatabaseInfo());
    }
}
import com.tech.multipledatasources.domain.DatabaseInfo;
import com.tech.multipledatasources.service.CustomerService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/customer")
public class CustomerController {
    
    private CustomerService customerService;

    public CustomerController(CustomerService customerService){
        this.customerService = customerService;
    }
    
    @GetMapping("/dsinfo")
    public ResponseEntity<DatabaseInfo> getDatasourceInfo(){
        return ResponseEntity.ok(customerService.getDatabaseInfo());
    }
}

运行应用程序

运行应用程序请求后,它将返回结果,该结果将指示我们刚刚在连接中创建的数据库。

以上是“在SpringBoot应用程序中使用多个数据源的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI