学生管理系统 数据连接版本(java和python的区别)
Python (PyMySQL) vs Java (JDBC) 数据库操作对比
本文对比了使用 PyMySQL (Python)和 JDBC(Java)操作 MySQL 数据库的核心差异,帮助有 Java 经验的开发者快速掌握 Python 的数据库编程。
1. 环境准备与驱动加载
| 步骤 | Python (PyMySQL) | Java (JDBC) |
|---|---|---|
| 安装驱动 | pip install pymysql |
下载 MySQL Connector/J(JAR 包),添加到 classpath |
| 导入包 | import pymysql |
import java.sql.* |
| 加载驱动类 | 无需显式加载 ,pip install 后直接可用 |
Class.forName("com.mysql.cj.jdbc.Driver") (JDBC 4.0 后可省略) |
2. 建立数据库连接
Python (PyMySQL)
python
conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="student_db",
charset="utf8mb4",
cursorclass=pymysql.cursors.DictCursor # 可选,返回字典
)
Java (JDBC)
java
String url = "jdbc:mysql://localhost:3306/student_db?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "123456";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
// 连接对象
}
| 对比项 | Python | Java |
|---|---|---|
| 连接字符串 | 命名参数形式 | JDBC URL + 参数 |
| 自动关闭 | 使用 with 语句或手动 close() |
使用 try-with-resources(推荐) |
| 返回结果形状 | 可指定 DictCursor 返回字典 |
返回 ResultSet,需手动映射 |
3. 执行查询(SELECT)
Python 示例
python
with conn.cursor() as cursor:
sql = "SELECT sid, name, age, score FROM students WHERE sid = %s"
cursor.execute(sql, ("S001",))
row = cursor.fetchone() # 返回字典
# row = {"sid":"S001", "name":"张三", "age":20, "score":85.5}
# 多条结果
cursor.execute("SELECT * FROM students")
all_rows = cursor.fetchall() # 返回字典列表
Java 示例
java
String sql = "SELECT sid, name, age, score FROM students WHERE sid = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "S001");
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
String sid = rs.getString("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
double score = rs.getDouble("score");
}
}
}
| 对比项 | Python | Java |
|---|---|---|
| 参数占位符 | %s(通用,不区分类型) |
?(位置参数) |
| 设置参数 | 通过元组 (value,) 传入 execute() |
pstmt.setXxx(index, value) |
| 获取结果 | fetchone() 返回字典或 None;fetchall() 返回列表 |
ResultSet 游标,需循环 next() |
| 字段取值 | 字典方式:row['name'] |
rs.getString("name") |
| 关闭资源 | with 自动关闭 cursor |
需要分别关闭 ResultSet、PreparedStatement(try-with-resources 自动) |
4. 插入数据(INSERT)
Python
python
sql = "INSERT INTO students (sid, name, age, score) VALUES (%s, %s, %s, %s)"
with conn.cursor() as cursor:
cursor.execute(sql, ("S002", "李四", 21, 92.5))
conn.commit()
Java
java
String sql = "INSERT INTO students (sid, name, age, score) VALUES (?, ?, ?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "S002");
pstmt.setString(2, "李四");
pstmt.setInt(3, 21);
pstmt.setDouble(4, 92.5);
int affected = pstmt.executeUpdate();
conn.commit();
}
| 对比项 | Python | Java |
|---|---|---|
| 执行方法 | cursor.execute() |
pstmt.executeUpdate() |
| 返回值 | 影响行数(可通过 cursor.rowcount 获得) |
返回 int 影响行数 |
| 自动提交 | 默认 关闭 (需手动 commit()) |
默认 自动提交 (可设置 conn.setAutoCommit(false)) |
5. 更新与删除
Python (更新)
python
sql = "UPDATE students SET name = %s, score = %s WHERE sid = %s"
with conn.cursor() as cursor:
affected = cursor.execute(sql, ("王五", 88.0, "S001"))
conn.commit()
Java (更新)
java
String sql = "UPDATE students SET name = ?, score = ? WHERE sid = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "王五");
pstmt.setDouble(2, 88.0);
pstmt.setString(3, "S001");
int affected = pstmt.executeUpdate();
conn.commit();
}
删除类似,只需改变 SQL 语句。
6. 事务管理
| 操作 | Python | Java |
|---|---|---|
| 关闭自动提交 | 连接创建后自动为手动提交模式 | conn.setAutoCommit(false) |
| 提交事务 | conn.commit() |
conn.commit() |
| 回滚事务 | conn.rollback() |
conn.rollback() |
| 异常处理中回滚 | except 块中执行 rollback() |
catch 块中执行 rollback() |
Python 典型事务模板
python
try:
with conn.cursor() as cursor:
cursor.execute(sql1, params1)
cursor.execute(sql2, params2)
conn.commit()
except pymysql.Error as e:
conn.rollback()
print(f"事务失败: {e}")
Java 典型事务模板
java
try {
conn.setAutoCommit(false);
try (PreparedStatement pstmt1 = conn.prepareStatement(sql1);
PreparedStatement pstmt2 = conn.prepareStatement(sql2)) {
pstmt1.executeUpdate();
pstmt2.executeUpdate();
conn.commit();
}
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
} finally {
conn.setAutoCommit(true);
}
7. 异常处理
| 方面 | Python | Java |
|---|---|---|
| 异常类 | pymysql.Error(及其子类) |
SQLException |
| 捕获方式 | try...except... |
try...catch... |
| 获取错误信息 | str(e) 或 e.args |
e.getMessage() |
| 资源清理 | 使用 with 自动管理 cursor 和 connection |
try-with-resources 自动管理 Connection、PreparedStatement、ResultSet |
8. 连接池对比(进阶)
| 特性 | Python | Java |
|---|---|---|
| 常用库 | DBUtils, SQLAlchemy (内置池) |
HikariCP, Apache DBCP, C3P0 |
| 简单示例 | pooled_db = PooledDB(pymysql, maxconnections=5, ...) |
HikariConfig + HikariDataSource |
| 自动归还连接 | 支持 | 支持 |
9. 代码风格与习惯
| 习惯 | Python | Java |
|---|---|---|
| 变量命名 | 蛇形命名法 student_id |
驼峰命名法 studentId |
| 上下文管理器 | with 自动管理资源 |
try-with-resources |
| 返回结果 | 更倾向于返回字典或对象列表 | 通常封装成 POJO 或返回 List<Entity> |
| SQL 拼接 | 永远使用参数化查询 (%s 占位符) |
永远使用 PreparedStatement |
| 获取自增主键 | cursor.lastrowid |
pstmt.getGeneratedKeys() |
10. 完整示例:查询并打印所有学生
Python 版本
python
def show_all_students():
conn = get_connection()
try:
with conn.cursor() as cursor:
cursor.execute("SELECT sid, name, age, score FROM students")
rows = cursor.fetchall()
for row in rows:
print(f"{row['sid']} {row['name']} {row['age']} {row['score']}")
except pymysql.Error as e:
print(e)
finally:
conn.close()
Java 版本
java
public void showAllStudents() {
String sql = "SELECT sid, name, age, score FROM students";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
String sid = rs.getString("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
double score = rs.getDouble("score");
System.out.printf("%s %s %d %.2f%n", sid, name, age, score);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
总结
| 操作 | Python 优势 | Java 优势 |
|---|---|---|
| 连接建立 | 命名参数更清晰 | JDBC URL 标准统一 |
| 查询执行 | fetchone()/fetchall() 直接返回字典,方便 |
强类型,编译期检查 |
| 参数设置 | 元组传参,自动匹配类型 | 需要按索引设置类型,繁琐但安全 |
| 事务管理 | 同样支持 commit/rollback | 同样支持 |
| 资源关闭 | with 语句极其简洁 |
try-with-resources 也很优雅 |
| 性能 | 纯 Python 略慢 | JVM 优化,通常更快 |
| 生态 | SQLAlchemy 等 ORM 强大 | MyBatis, Hibernate 成熟 |
核心思想 :无论 Python 还是 Java,数据库编程的流程都是一致的:建立连接 → 创建语句 → 执行 SQL → 处理结果 → 提交/回滚 → 关闭资源。语法差异只是表面,理解事务、连接池、参数化防注入等概念才是关键。
对于从 Java 转 Python 的开发者,推荐使用 PyMySQL + 字典游标 ,并结合 with 语句管理资源,可以快速写出简洁、安全的数据库代码。