说明:
本文由人机协作生成,作者提供主要思路,借助 AI 通过多轮迭代逐步优化生成。
核心思路:
体验"在AI辅助下,从零创建 Maven 项目,引入一个第三方库,并跑通一个核心功能"的全流程。
| 原始项目 | 90分钟极简版核心目标 | 技术栈极简版 | 功能要求极简版 |
|---|---|---|---|
| 学生管理系统 | 连接数据库,执行一次插入和查询 | 仅保留 SQLite JDBC | 1. 创建数据库和一张学生表。2. 插入一条学生数据。3. 查询并打印所有学生。可通过AI生成测试数据。 |
Maven 项目的优势
Maven 是 Java 项目的构建 + 依赖管理工具,对比以往手动建项目、手动下载 jar 包的方式,Maven 项目为编程提供了太多便利性。只需在 pom.xml 里写几行依赖配置,Maven 自动就会主动完成:
- 从中央仓库下载对应版本的 jar 包;
- 自动下载 "依赖的依赖"(比如 sqlite-jdbc 依赖的 slf4j-api);
- 所有依赖统一存在本地仓库,其他项目可复用,不用重复下载。
而且还可以统一编译和运行环境,避免版本冲突。比如 pom.xml 里配置了 JDK 21 的编译规则:
java
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
以及,方便我们的拓展和团队的协作。
SQLite 基础知识
一、SQLite 的特点
首先,我们先来对此次项目的核心工具 -- SQLite 做一个基础认识:
SQLite 是一款轻量级、嵌入式、零配置的关系型数据库,不用装服务器,一个文件就是一个数据库,适合学习、小型项目;而我们常见的 MySQL 需要先开服务器,适合大规模场景。
多方对比:
| 特性 | SQLite | MySQL/PostgreSQL |
|---|---|---|
| 部署方式 | 嵌入式(无独立服务进程) | 客户端 / 服务端(需启动数据库服务) |
| 配置难度 | 零配置(无需安装、无需账号密码) | 需安装、配置端口 / 账号 / 权限 |
| 数据存储 | 单文件(比如此次项目的 student.db文件) | 多文件 / 目录存储(分散在服务器) |
| 适用场景 | 本地小型应用、嵌入式设备、测试 | 大型网站、高并发服务、企业系统 |
二、SQLite 核心概念
1. 数据库文件(.db/.sqlite)
1)项目里的 student.db 就是一个完整的 SQLite 数据库,所有表、数据都存在这个文件里。
2)删除这个文件相当于清空整个数据库,重新运行代码会自动重建空文件。
2. 表(Table)
1)创建的 student 表是数据的容器,类似 Excel 里的工作表;
2)表由 **"字段(列)+ 数据行"**组成,比如 student 表的字段是 id / name / age / className。
3. 字段(Column)和数据类型
SQLite 是 "弱类型" 数据库(比 MySQL 灵活),常用字段类型如下:
| 类型 | 用途 | 项目示例 |
|---|---|---|
| INTEGER | 整数(ID、年龄等) | id(自增主键)、age |
| TEXT | 文本(字符串) | name、className |
| REAL | 浮点数(小数) | 比如 score(成绩) |
| BLOB | 二进制数据(图片等) | 新手很少用 |
4. 主键(PRIMARY KEY)
1)主键是表中唯一标识一行数据的字段(比如 id),以此保证每条数据不重复;
2)此次项目里所使用的 AUTOINCREMENT 是 SQLite 的自增特性,插入数据时不用手动填 ID,数据库会自动生成 1、2、3...
三、SQLite 常用的 SQL 语法
1. 表的创建(CREATE TABLE)
java
-- 基础语法
CREATE TABLE IF NOT EXISTS 表名 (
字段名1 类型 约束,
字段名2 类型 约束,
...
);
-- 示例:student表
CREATE TABLE IF NOT EXISTS student (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 自增主键
name TEXT NOT NULL, -- 非空(姓名不能为空)
age INTEGER,
className TEXT
);
注意:
1)IF NOT EXISTS:避免重复创建表(虽然运行多次代码也不会报错)。
2)NOT NULL:约束字段不能为空(比如姓名必须填,年龄可选)。
2. 数据的插入(INSERT)
java
-- 基础语法(自增ID不用填)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...);
-- 示例:插入张三的信息
INSERT INTO student (name, age, className) VALUES ('张三', 20, '网安2411');
3. 数据的查询(SELECT)
java
-- 查询所有字段
SELECT * FROM 表名;
-- 示例:查所有学生
SELECT * FROM student;
-- 条件查询(拓展):查网安2411班的学生
SELECT * FROM student WHERE className = '网安2411';
-- 排序查询(拓展):按年龄升序排列
SELECT * FROM student ORDER BY age ASC;
4. 数据的修改(UPDATE,拓展)
java
-- 基础语法
UPDATE 表名 SET 字段1=新值 WHERE 条件;
-- 示例:把张三的年龄改成21
UPDATE student SET age=21 WHERE name='张三';
5. 数据的删除(DELETE,拓展)
java
-- 基础语法
DELETE FROM 表名 WHERE 条件;
-- 示例:删除ID为1的学生
DELETE FROM student WHERE id=1;
-- 清空表(保留表结构)
DELETE FROM student;
注意事项:手写 ID 容易出现主键冲突的错误,使用自增 ID 可以很好的规避掉这个问题。
代码展示
一、项目层级结构

二、代码
1. Main.java 文件
java
package jmu.net;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/**
* 学生管理系统
*/
public class Main {
// SQLite数据库地址
private static final String DB_URL = "jdbc:sqlite:student.db";
// 全局扫描器(避免重复创建)
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
// 1. 创建学生表
createStudentTable();
// 2. 控制台动态添加学生(循环添加,支持多次输入)
addStudentByConsole();
// 3. 查询并打印所有学生
queryAllStudents();
// 关闭扫描器
scanner.close();
}
/**
* 创建学生表(ID自增)
*/
private static void createStudentTable() {
String createSql = "CREATE TABLE IF NOT EXISTS student (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"name TEXT NOT NULL," +
"age INTEGER," +
"className TEXT)";
try (Connection conn = DriverManager.getConnection(DB_URL);
Statement stmt = conn.createStatement()) {
stmt.execute(createSql);
System.out.println("✅ 学生表创建/加载成功!");
} catch (SQLException e) {
System.err.println("❌ 创建表失败:" + e.getMessage());
}
}
/**
* 控制台动态输入学生信息并添加
*/
private static void addStudentByConsole() {
System.out.println("\n===== 开始添加学生信息 =====");
while (true) {
// 1. 输入姓名
System.out.print("请输入学生姓名(输入'q'退出添加):");
String name = scanner.nextLine().trim();
// 退出条件:输入q/Q
if ("q".equalsIgnoreCase(name)) {
System.out.println("✅ 退出学生添加流程!");
break;
}
// 姓名不能为空
if (name.isEmpty()) {
System.err.println("❌ 姓名不能为空,请重新输入!");
continue;
}
// 2. 输入年龄(处理非数字异常)
int age = 0;
while (true) {
System.out.print("请输入学生年龄:");
String ageStr = scanner.nextLine().trim();
try {
age = Integer.parseInt(ageStr);
if (age <= 0 || age > 100) {
System.err.println("❌ 年龄需在1-100之间,请重新输入!");
continue;
}
break; // 年龄输入正确,退出循环
} catch (NumberFormatException e) {
System.err.println("❌ 年龄必须是数字,请重新输入!");
}
}
// 3. 输入班级
System.out.print("请输入学生班级:");
String className = scanner.nextLine().trim();
if (className.isEmpty()) {
className = "未填写"; // 班级为空时默认值
}
// 4. 插入数据
insertStudent(name, age, className);
System.out.println("------------------------\n");
}
}
/**
* 插入学生数据(底层方法)
*/
private static void insertStudent(String name, int age, String className) {
String insertSql = "INSERT INTO student (name, age, className) VALUES (?, ?, ?)";
try (Connection conn = DriverManager.getConnection(DB_URL);
PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
pstmt.setString(1, name);
pstmt.setInt(2, age);
pstmt.setString(3, className);
pstmt.executeUpdate();
System.out.println("✅ 学生[" + name + "]添加成功!");
} catch (SQLException e) {
System.err.println("❌ 插入数据失败:" + e.getMessage());
}
}
/**
* 查询所有学生并打印
*/
private static void queryAllStudents() {
String querySql = "SELECT * FROM student";
try (Connection conn = DriverManager.getConnection(DB_URL);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(querySql)) {
System.out.println("\n===== 所有学生信息 ======");
boolean hasData = false;
while (rs.next()) {
hasData = true;
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String className = rs.getString("className");
System.out.printf("ID:%d,姓名:%s,年龄:%d,班级:%s%n",
id, name, age, className);
}
if (!hasData) {
System.out.println("暂无学生数据");
}
} catch (SQLException e) {
System.err.println("❌ 查询数据失败:" + e.getMessage());
}
}
}
2. pom.xml 文件
java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jmu.net</groupId>
<artifactId>StudentManagement</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 统一SLF4J版本,避免冲突 -->
<slf4j.version>1.7.36</slf4j.version>
</properties>
<!-- 引入依赖 -->
<dependencies>
<!-- SQLite JDBC依赖 -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.2.0</version>
</dependency>
<!-- SLF4J简单实现,消除日志提示 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope> <!-- 仅运行时生效,不影响编译 -->
</dependency>
</dependencies>
<!-- 添加编译插件 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>21</source>
<target>21</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
运行结果展示
一、控制台输出

二、student.db 文件展示

如图,在 IDEA 的左侧项目栏中,找到 student.db 文件,直接点击即可打开并查看我们生成的学生信息表:

student.db 是程序执行:
java
Connection conn = DriverManager.getConnection("jdbc:sqlite:student.db");
获取数据库连接时自动生成的;执行 createStudentTable() 创建学生表以及 addStudentByConsole() 插入数据后,表和数据会被持久化到该文件中。
学习心得
此次实验还体验了 Maven 项目的打包功能:
打开右侧 Maven 面板 → 先点 clean → 再点 package。一定要先执行 clean 把旧的打包文件清空再执行 package!!

等待一会,项目就会自动被打包好了,打包成功后,会在项目的 target 目录下生成 jar 包,文件名格式是:项目名-版本号.jar,如下图我红色框住位置:

那我们来验证一下项目的打包效果吧:
打开终端,进入 target 目录,执行命令运行 jar 包

上面显示:jar 包缺少 "主清单属性",简单说就是 Maven 打包时没告诉 jar 包哪个类是程序的入口,所以运行 java -jar 时不知道从哪里启动程序。要想解决这个问题依然得依靠我们的 pom.xml,我们只要在其中中添加主类配置就好了。
打开 IDEA 里的pom.xml,找到<build>标签(如果没有就新增),添加 maven-jar-plugin 配置:
java
<build>
<plugins>
<!-- 原有编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>21</source>
<target>21</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- 新增:指定主类,解决"没有主清单属性"问题 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<!-- 这里写你的主类全路径:包名+类名 -->
<mainClass>jmu.net.Main</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
那我的 pom.xml 文件修改好就是这样子的:
java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jmu.net</groupId>
<artifactId>StudentManagement</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>1.7.36</slf4j.version>
</properties>
<dependencies>
<!-- SQLite JDBC依赖 -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.2.0</version>
</dependency>
<!-- SLF4J日志依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 1. 编译插件(指定JDK版本) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>21</source>
<target>21</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- 2. 打包插件(核心!解决主类+依赖缺失问题) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<archive>
<manifest>
<!-- 必须和Main类包名+类名一致! -->
<mainClass>jmu.net.Main</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<!-- 打包成"包含所有依赖的胖jar" -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
那现在我们只要重新打包就好了,和之前的方式一样:打开右侧 Maven 面板 → 先点 clean → 再点 package。
现在我们重新执行 jar 包:

成功运行,不过中文的地方有乱码,我们可以更改控制台的编码方式,执行 chcp 65001 命令就可以正常输出中文了:

当然,生成的数据库在 target 目录下就可以找到:


其实实验做下来的最大感触就是 Maven 项目的便利性。在创建项目的时候,它会自动的帮我匹配下载需要的资源包、配置文件、依赖。pom.xml 则是 Maven 项目的核心配置文件,简单理解的话,它是 Maven 管理项目的 "说明书",告诉 Maven 这个项目的**"身份、依赖、编译规则、打包方式"**等关键信息,编程过程中只用在意核心功能的构建。这次实验让我切实感受到 Maven 在项目管理上的优势,后续希望能进一步尝试 Maven 的多人协作模式。