本篇文章,我將為大家介紹如何通過使用 Oracle 數(shù)據(jù)庫的簡化應用程序在 SpringBoot 應用程序中使用多個數(shù)據(jù)源。下面是詳情內容,希望能夠對各位讀者有所幫助。
項目創(chuàng)建
我們可以使用Spring Initializer創(chuàng)建具有以下依賴項的示例應用程序:
選擇后,請按“生成”按鈕并將項目另存為 zip 文件。
我使用 Eclipse 作為 Java IDE,但你可以使用任何你喜歡的方式來開發(fā)示例應用程序。打開 zip 文件,并將該文件夾作為 Eclipse 中的 Maven 項目導入。項目結構應如下所示:
屬性文件
首先,讓我們在 application.properties 文件中定義兩個不同的數(shù)據(jù)源設置,如下所示:
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 數(shù)據(jù)庫,但你也可以使用其他數(shù)據(jù)庫,只要相應地更改 ?driverClassName
?。
數(shù)據(jù)源配置
為了創(chuàng)建 ?DataSource bean
?,我創(chuàng)建了一個 ?DatasourceConfig
?類并將其注釋為配置,并將兩個數(shù)據(jù)源添加為兩個不同的 ?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;
}
}
數(shù)據(jù)訪問
我使用了 ?JdbcTemplate
?作為數(shù)據(jù)訪問。要創(chuàng)建 ?DAO
?接口,請在 ?com.tech.multipledatasources.dao
? 包下添加 ?IDatabaseDAO
?接口,如下所示:
import com.tech.multipledatasources.domain.DatabaseInfo;
public interface IDatabaseDAO {
public DatabaseInfo getDatabaseInfo();
}
我對這個接口做了兩種不同的實現(xiàn),因為即使它是一個簡單的應用程序,現(xiàn)實生活中的場景也會有所不同。
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 數(shù)據(jù)庫。如果您打算使用不同的數(shù)據(jù)庫,則需要更改此語句。
我使用構造函數(shù)級別的依賴注入來注入數(shù)據(jù)源,并使用 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();
}
}
異常處理
我在下面創(chuàng)建了 ?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);
}
}
控制器
我創(chuàng)建了兩個控制器。一種用于計費,一種用于客戶請求;將兩個服務類注入控制器。
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());
}
}
運行應用程序
運行?應用程序
?和?請求
?后,它將返回結果,該結果將指示我們剛剛在連接中創(chuàng)建的數(shù)據(jù)庫。
關于Spring boot應用程序中如何使用多個數(shù)據(jù)源的內容就介紹到此結束了,感謝各位讀者的閱讀。