KennethCheng 0f521d58bf docs: 新增 README 与代码审查
- README.md:项目结构、技术栈、三条业务需求、MySQL 表、构建运行步骤、已知问题
- CODE_REVIEW.md:分三级(严重/主要/次要)列出 11 个发现,含密码硬编码、空类、Any 分发等

本次仅提交两份文档;工作树里 App.scala 的 data path 切换与 ratings_all.csv 由用户后续单独提交
2026-09-21 22:24:35 +08:00
2026-09-21 11:21:55 +08:00
2026-09-21 17:00:40 +08:00
2026-09-21 11:21:55 +08:00
2026-09-21 11:21:55 +08:00
2026-09-21 22:24:35 +08:00

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, genres
    • genres 多个类别用 | 分隔(如 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();CSV inferSchema=true
  • 🟡 无单元测试(JUnit 依赖已引但 src/test/ 空)

参考

S
Description
No description provided
Readme
1.2 MiB
Languages
Scala 100%