26.2.1 数据仓库的定义
定义 :数据仓库是一种用于存储和管理大量结构化数据的数据库系统,用于支持企业级数据分析和决策。
作用:
- 提供统一的数据存储。
- 支持复杂的数据分析。
- 提高决策效率。
常见的数据仓库:
- Apache Hive:Apache Hive是一种基于Hadoop的数据仓库工具。
- Apache HBase:Apache HBase是一种基于Hadoop的列式数据库。
- Amazon Redshift:Amazon Redshift是一种基于云计算的数据仓库。
- Google BigQuery:Google BigQuery是一种基于云计算的数据仓库。
✅ 结论:数据仓库是一种用于存储和管理大量结构化数据的数据库系统,作用是提供统一的数据存储、支持复杂的数据分析、提高决策效率。
26.2.2 ETL工具的定义
定义 :ETL工具是一种用于数据抽取(Extract)、转换(Transform)和加载(Load)的工具,用于将数据从源系统导入到数据仓库。
作用:
- 实现数据的抽取。
- 实现数据的转换。
- 实现数据的加载。
常见的ETL工具:
- Apache Spark:Apache Spark是一种开源的分布式计算框架,支持ETL操作。
- Apache Flink:Apache Flink是一种开源的流处理框架,支持ETL操作。
- Apache Airflow:Apache Airflow是一种开源的调度工具,用于调度ETL任务。
- Talend:Talend是一种开源的ETL工具。
✅ 结论:ETL工具是一种用于数据抽取、转换和加载的工具,作用是实现数据的抽取、转换、加载。
26.3 Spring Boot与数据仓库的集成
Spring Boot与数据仓库的集成是Java开发中的重要内容。
26.3.1 集成Apache Hive的步骤
定义 :集成Apache Hive的步骤是指使用Spring Boot与Apache Hive集成的方法。
步骤:
- 创建Spring Boot项目。
- 添加所需的依赖。
- 配置Apache Hive。
- 创建数据访问层。
- 创建业务层。
- 创建控制器类。
- 测试应用。
示例 :
pom.xml文件中的依赖:
xml
<dependencies>
<!-- Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Hive依赖 -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.3.1</version>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
AI写代码xml
1234567891011121314151617181920212223242526
application.properties文件中的配置:
ini
# 服务器端口
server.port=8080
# Hive连接信息
spring.datasource.url=jdbc:hive2://localhost:10000/default
spring.datasource.driver-class-name=org.apache.hive.jdbc.HiveDriver
spring.datasource.username=hive
spring.datasource.password=
AI写代码properties
12345678
实体类 **:
arduino
public class Product {
private Long id;
private String productId;
private String productName;
private double price;
private int sales;
public Product() {
}
public Product(Long id, String productId, String productName, double price, int sales) {
this.id = id;
this.productId = productId;
this.productName = productName;
this.price = price;
this.sales = sales;
}
// Getter和Setter方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getSales() {
return sales;
}
public void setSales(int sales) {
this.sales = sales;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", productId='" + productId + ''' +
", productName='" + productName + ''' +
", price=" + price +
", sales=" + sales +
'}';
}
}
AI写代码java
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
Repository接口:
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Repository
public class ProductRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Product> getAllProducts() {
String sql = "SELECT * FROM product";
return jdbcTemplate.query(sql, new RowMapper<Product>() {
@Override
public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
Product product = new Product();
product.setId(rs.getLong("id"));
product.setProductId(rs.getString("product_id"));
product.setProductName(rs.getString("product_name"));
product.setPrice(rs.getDouble("price"));
product.setSales(rs.getInt("sales"));
return product;
}
});
}
public Product getProductById(Long id) {
String sql = "SELECT * FROM product WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new RowMapper<Product>() {
@Override
public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
Product product = new Product();
product.setId(rs.getLong("id"));
product.setProductId(rs.getString("product_id"));
product.setProductName(rs.getString("product_name"));
product.setPrice(rs.getDouble("price"));
product.setSales(rs.getInt("sales"));
return product;
}
});
}
public void addProduct(Product product) {
String sql = "INSERT INTO product (product_id, product_name, price, sales) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(sql, product.getProductId(), product.getProductName(), product.getPrice(), product.getSales());
}
public void updateProduct(Product product) {
String sql = "UPDATE product SET product_id = ?, product_name = ?, price = ?, sales = ? WHERE id = ?";
jdbcTemplate.update(sql, product.getProductId(), product.getProductName(), product.getPrice(), product.getSales(), product.getId());
}
public void deleteProduct(Long id) {
String sql = "DELETE FROM product WHERE id = ?";
jdbcTemplate.update(sql, id);
}
}
AI写代码java
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
Service类:
typescript
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public List<Product> getAllProducts() {
return productRepository.getAllProducts();
}
public Product getProductById(Long id) {
return productRepository.getProductById(id);
}
public void addProduct(Product product) {
productRepository.addProduct(product);
}
public void updateProduct(Product product) {
productRepository.updateProduct(product);
}
public void deleteProduct(Long id) {
productRepository.deleteProduct(id);
}
}
AI写代码java
运行
123456789101112131415161718192021222324252627282930
控制器 **类:
less
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/")
public List<Product> getAllProducts() {
return productService.getAllProducts();
}
@GetMapping("/{id}")
public Product getProductById(@PathVariable Long id) {
return productService.getProductById(id);
}
@PostMapping("/")
public void addProduct(@RequestBody Product product) {
productService.addProduct(product);
}
@PutMapping("/{id}")
public void updateProduct(@PathVariable Long id, @RequestBody Product product) {
product.setId(id);
productService.updateProduct(product);
}
@DeleteMapping("/{id}")
public void deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
}
}
AI写代码java
运行
12345678910111213141516171819202122232425262728293031323334353637
应用启动类:
typescript
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HiveApplication {
public static void main(String[] args) {
SpringApplication.run(HiveApplication.class, args);
}
}
AI写代码java
运行
123456789
测试类:
java
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HiveApplicationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
void contextLoads() {
}
@Test
void testGetAllProducts() {
List<Product> products = restTemplate.getForObject("http://localhost:" + port + "/api/products/", List.class);
assertThat(products).isNotNull();
assertThat(products.size()).isGreaterThanOrEqualTo(0);
}
@Test
void testAddProduct() {
Product product = new Product(null, "P001", "手机", 1000.0, 100);
restTemplate.postForObject("http://localhost:" + port + "/api/products/", product, Product.class);
List<Product> products = restTemplate.getForObject("http://localhost:" + port + "/api/products/", List.class);
assertThat(products).isNotNull();
assertThat(products.size()).isGreaterThanOrEqualTo(1);
}
}
AI写代码java
运行
123456789101112131415161718192021222324252627282930313233343536
✅ 结论:集成Apache Hive的步骤包括创建Spring Boot项目、添加所需的依赖、配置Apache Hive、创建数据访问层、创建业务层、创建控制器类、测试应用。
26.4 Spring Boot与ETL工具的集成
Spring Boot与ETL工具的集成是Java开发中的重要内容。
26.4.1 集成Apache Spark的步骤
定义 :集成Apache Spark的步骤是指使用Spring Boot与Apache Spark集成的方法。
步骤:
- 创建Spring Boot项目。
- 添加所需的依赖。
- 配置Apache Spark。
- 创建ETL任务。
- 测试应用。
示例 :
pom.xml文件中的依赖:
xml
<dependencies>
<!-- Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spark依赖 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.1.2</version>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
AI写代码xml
1234567891011121314151617181920212223242526
application.properties文件中的配置:
ini
# 服务器端口
server.port=8080
# Spark配置
spark.master=local[*]
spark.app.name=ETLExample
AI写代码properties
123456
ETL任务类:
java
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
public class ETLJob {
@Value("${spark.master}")
private String master;
@Value("${spark.app.name}")
private String appName;
public void runETL() {
SparkSession sparkSession = SparkSession.builder()
.master(master)
.appName(appName)
.getOrCreate();
// 读取源数据
Dataset<Row> sourceData = sparkSession.read()
.format("csv")
.option("header", "true")
.option("inferSchema", "true")
.load("src/main/resources/source-data.csv");
// 数据转换
Dataset<Row> transformedData = sourceData.select(
sourceData.col("id"),
sourceData.col("product_id"),
sourceData.col("product_name"),
sourceData.col("price"),
sourceData.col("sales")
).filter(sourceData.col("sales") > 100);
// 写入目标数据
Properties connectionProperties = new Properties();
connectionProperties.put("user", "hive");
connectionProperties.put("password", "");
transformedData.write()
.mode("overwrite")
.jdbc("jdbc:hive2://localhost:10000/default", "transformed_product", connectionProperties);
sparkSession.stop();
}
}
AI写代码java
运行
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
控制器类:
kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/etl")
public class ETLController {
@Autowired
private ETLScheduler etlScheduler;
@PostMapping("/run")
public String runETL() {
etlScheduler.runETL();
return "ETL任务已启动";
}
}
AI写代码java
运行
123456789101112131415
调度器类:
typescript
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ETLScheduler {
@Autowired
private ETLJob etlJob;
@Scheduled(cron = "0 0 0 * * ?") // 每天凌晨0点执行
public void runETL() {
etlJob.runETL();
}
public void runETLNow() {
etlJob.runETL();
}
}
AI写代码java
运行
123456789101112131415161718
应用启动类:
typescript
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ETLApplication {
public static void main(String[] args) {
SpringApplication.run(ETLApplication.class, args);
}
}
AI写代码java
运行
1234567891011
测试类:
typescript
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ETLApplicationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
void contextLoads() {
}
@Test
void testRunETL() {
String response = restTemplate.postForObject("http://localhost:" + port + "/api/etl/run", null, String.class);
assertThat(response).contains("ETL任务已启动");
}
}
AI写代码java
运行
1234567891011121314151617181920212223242526
✅ 结论:集成Apache Spark的步骤包括创建Spring Boot项目、添加所需的依赖、配置Apache Spark、创建ETL任务、测试应用。
26.5 Spring Boot的实际应用场景
在实际开发中,Spring Boot数据仓库与ETL工具集成的应用场景非常广泛,如:
- 实现产品信息的ETL任务。
- 实现用户信息的ETL任务。
- 实现订单信息的ETL任务。
- 实现销售数据的ETL任务。
示例:
typescript
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
class ETLJob {
@Value("${spark.master}")
private String master;
@Value("${spark.app.name}")
private String appName;
public void runETL() {
SparkSession sparkSession = SparkSession.builder()
.master(master)
.appName(appName)
.getOrCreate();
// 读取源数据
Dataset<Row> sourceData = sparkSession.read()
.format("csv")
.option("header", "true")
.option("inferSchema", "true")
.load("src/main/resources/source-data.csv");
// 数据转换
Dataset<Row> transformedData = sourceData.select(
sourceData.col("id"),
sourceData.col("product_id"),
sourceData.col("product_name"),
sourceData.col("price"),
sourceData.col("sales")
).filter(sourceData.col("sales") > 100);
// 写入目标数据
Properties connectionProperties = new Properties();
connectionProperties.put("user", "hive");
connectionProperties.put("password", "");
transformedData.write()
.mode("overwrite")
.jdbc("jdbc:hive2://localhost:10000/default", "transformed_product", connectionProperties);
sparkSession.stop();
}
}
@RestController
@RequestMapping("/api/etl")
class ETLController {
@Autowired
private ETLScheduler etlScheduler;
@PostMapping("/run")
public String runETL() {
etlScheduler.runETL();
return "ETL任务已启动";
}
}
@Component
class ETLScheduler {
@Autowired
private ETLJob etlJob;
@Scheduled(cron = "0 0 0 * * ?") // 每天凌晨0点执行
public void runETL() {
etlJob.runETL();
}
public void runETLNow() {
etlJob.runETL();
}
}
@SpringBootApplication
@EnableScheduling
public class ETLApplication {
public static void main(String[] args) {
SpringApplication.run(ETLApplication.class, args);
}
}
// 测试类
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ETLApplicationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
void contextLoads() {
}
@Test
void testRunETL() {
String response = restTemplate.postForObject("http://localhost:" + port + "/api/etl/run", null, String.class);
assertThat(response).contains("ETL任务已启动");
}
}
AI写代码java
运行
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
✅ 结论:在实际开发中,Spring Boot数据仓库与ETL工具集成的应用场景非常广泛,需要根据实际问题选择合适的数据仓库和ETL工具。
总结
本章我们学习了Spring Boot数据仓库与ETL工具集成,包括数据仓库的定义与特点、ETL工具的定义与特点、Spring Boot与数据仓库的集成、Spring Boot与ETL工具的集成、Spring Boot的实际应用场景,学会了在实际开发中处理数据仓库与ETL工具集成问题。其中,数据仓库的定义与特点、ETL工具的定义与特点、Spring Boot与数据仓库的集成、Spring Boot与ETL工具的集成、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。