Maven 项目实战入门之--学生管理系统

说明:

本文由人机协作生成,作者提供主要思路,借助 AI 通过多轮迭代逐步优化生成。

核心思路:

体验"在AI辅助下,从零创建 Maven 项目,引入一个第三方库,并跑通一个核心功能"的全流程。

原始项目 90分钟极简版核心目标 技术栈极简版 功能要求极简版
学生管理系统 连接数据库,执行一次插入和查询 仅保留 SQLite JDBC 1. 创建数据库和一张学生表。2. 插入一条学生数据。3. 查询并打印所有学生。可通过AI生成测试数据。

Maven 项目的优势

Maven 是 Java 项目的构建 + 依赖管理工具,对比以往手动建项目、手动下载 jar 包的方式,Maven 项目为编程提供了太多便利性。只需在 pom.xml 里写几行依赖配置,Maven 自动就会主动完成:

  1. 从中央仓库下载对应版本的 jar 包;
  2. 自动下载 "依赖的依赖"(比如 sqlite-jdbc 依赖的 slf4j-api);
  3. 所有依赖统一存在本地仓库,其他项目可复用,不用重复下载。

而且还可以统一编译和运行环境,避免版本冲突。比如 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 的多人协作模式。

相关推荐
晨光32112 小时前
Day34 模块与包的导入
java·前端·python
知行合一。。。2 小时前
Python--01--核心基础
android·java·python
计算机毕设指导62 小时前
基于微信小程序的水上警务通系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
陌生的人儿2 小时前
老年痴呆患者心血管防护,硝酸甘油使用需 “专人监护”
java·eclipse·tomcat·maven·0.3mg硝酸甘油舌下片
他是龙5512 小时前
46:SQLMap实战全攻略(猜解/权限/绕过/调试)
数据库·oracle
冷雨夜中漫步2 小时前
Java类加载机制——双亲委派与自定义类加载器
java·开发语言·python
一位代码2 小时前
mysql | 环境变量问题及其配置方法详解
数据库·mysql
煎蛋学姐2 小时前
SSM校企协同育人平台j670k(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·ssm 框架开发
SadSunset2 小时前
(29)阶段性个人总结
java