master
- README.md:项目结构、技术栈、三条业务需求、MySQL 表、构建运行步骤、已知问题 - CODE_REVIEW.md:分三级(严重/主要/次要)列出 11 个发现,含密码硬编码、空类、Any 分发等 本次仅提交两份文档;工作树里 App.scala 的 data path 切换与 ratings_all.csv 由用户后续单独提交
spark_project
MovieLens 风格数据集上的三条聚合分析练习项目:基于 Spark SQL + MySQL,把三条统计结果写入数据库。
学习 / 练手项目;不是生产系统。详见
CODE_REVIEW.md。
项目简介
读取两份 CSV:
data/movies.csv:电影元数据(movieId, title, genres)data/ratings_all.csv(或data/ratings.csv,小样本):用户评分(userId, movieId, rating, timestamp)
完成三条业务需求:
| 编号 | 描述 |
|---|---|
| 需求 1 | 评分次数 > 5000 的电影中,按平均分 Top 10,输出 movieId / title / avgRating |
| 需求 2 | 按 genres 拆分后,每个类别计算平均评分 |
| 需求 3 | 按评分次数 Top 10 的电影,输出 movieId / title / ratingCount |
三条结果分别写入 MySQL 表 top_ten_avg_ratings / genres_average_rating / movie_rating_count,使用 REPLACE INTO(基于各自 unique key 做 upsert)。
技术栈
| 组件 | 版本 |
|---|---|
| Scala | 2.11.12 |
| Apache Spark | 2.4.3(Spark Core + Spark SQL) |
| MySQL Connector/J | 8.0.28 |
| HikariCP | 4.0.3 |
| Commons DBUtils | 1.6 |
| 构建工具 | Maven 3.x + scala-maven-plugin 4.8.1 |
| Java 目标 | 8 |
目录结构
spark_project/
├── pom.xml
├── README.md
├── CODE_REVIEW.md
├── data/
│ ├── movies.csv # 电影元数据
│ ├── ratings.csv # 小样本评分
│ └── ratings_all.csv # 全量评分
└── src/
├── main/
│ ├── resources/
│ │ ├── create_table.sql # MySQL DDL
│ │ └── log4j.properties # 日志配置(stdout only,error 级别)
│ └── scala/com/example/
│ ├── spark/
│ │ ├── App.scala # 入口,三个 SQL 需求
│ │ └── Entitys.scala # case class:Movie / Rating / 三种结果
│ └── utils/
│ └── JDBCUtil.scala # HikariCP + DBUtils 写入 MySQL
└── test/ # 空
数据约定
data/movies.csv字段:movieId, title, genresgenres多个类别用|分隔(如Adventure|Animation|Children|Comedy|Fantasy)
data/ratings.csv/data/ratings_all.csv字段:userId, movieId, rating, timestamp- 默认入口读
ratings_all.csv;开发期可在App.scala:9切回ratings.csv
MySQL 表结构
详见 src/main/resources/create_table.sql。三张表统一字段:id 自增主键、update_time 默认当前时间、业务字段 + 唯一键。
-- 需求 1 结果
create table top_ten_avg_ratings (
id int(11) not null AUTO_INCREMENT,
movie_id int(11) not null,
title varchar(200) not null,
avg_rating decimal(10, 2) not null,
update_time datetime default current_timestamp,
primary key (id),
unique key movie_id_unique (movie_id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
⚠️ 实际库 / 表创建请先用
create_table.sql跑一遍。
配置
JDBCUtil.scala 当前把连接信息硬编码:
private val user = "root"
private val password = "root123456"
private val url = "jdbc:mysql://192.168.48.10:3306/test"
生产前必须改成外部配置(application.conf / 环境变量 / 命令行参数)。详见 CODE_REVIEW.md 第 1 条。
App.scala:14 的 master("local[2]") 也是硬编码,集群提交前请改为从参数传入。
构建与运行
前置条件
- JDK 8
- Maven 3.6+
- MySQL 8.x(本地或局域网),能访问
192.168.48.10:3306
步骤
# 1. 建表
mysql -h 192.168.48.10 -P 3306 -u root -p < src/main/resources/create_table.sql
# 2. 编译 + 打 fat-jar(assembly 插件已配置)
mvn -P dev clean package
# 3. dev profile:spark-core / spark-sql 是 compile 作用域,IDE 直接跑 App.main 即可
# build_pkg profile:provided 作用域,打成可提交到集群的 jar
# 4. 本地跑(也可直接 java -jar)
java -cp target/spark_project-1.0-SNAPSHOT-jar-with-dependencies.jar com.example.spark.App
Maven Profile 说明
| profile | 用途 | Spark 依赖 scope |
|---|---|---|
dev |
IDE 本地跑、单元测试 | compile |
build_pkg |
打胖包丢到集群跑 | provided |
已知问题 / TODO
详见 CODE_REVIEW.md 完整清单,优先级最高的:
- 🔴 MySQL 密码硬编码
- 🔴
create_table.sql中avg_rating字段注释残留 - 🟠
Entitys.scala死类 + 字段类型与 SQL 不一致 - 🟠
insert2Mysql(res: Any)用 Any 做运行时分发 - 🟠
SparkSession未stop();CSVinferSchema=true - 🟡 无单元测试(JUnit 依赖已引但
src/test/空)
参考
- MovieLens 数据集:https://grouplens.org/datasets/movielens/
- Spark SQL 文档(2.4.x):https://spark.apache.org/docs/2.4.3/sql-programming-guide.html
- HikariCP 配置:https://github.com/brettwooldridge/HikariCP
Languages
Scala
100%