- JDBC (Java Database Connectivity):这是 Java 官方提供的、最基础的数据库连接方式,它适用于所有关系型数据库(如 MySQL, Oracle, SQL Server, PostgreSQL 等),代码量稍多,但灵活性和可控性最高。
- MyBatis / JPA:这是目前主流的 ORM (Object-Relational Mapping) 框架,它们将数据库表和 Java 对象进行映射,让你可以用面向对象的方式操作数据库,极大地简化了数据访问层的代码。
下面我将分别详细介绍这两种方式,并提供从简单到复杂的完整示例。

使用原生 JDBC (最基础、最灵活)
使用 JDBC 的核心步骤是:
- 加载数据库驱动。
- 获取数据库连接。
- 创建
Statement或PreparedStatement对象。 - 执行查询,返回
ResultSet结果集。 - 遍历
ResultSet,将数据封装到 Java 对象中。 - 关闭所有资源(
ResultSet,Statement,Connection)。
完整示例:查询用户列表
假设我们有一个 users 表,结构如下:
CREATE TABLE `users` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL, `email` VARCHAR(100) NOT NULL, `age` INT );
准备工作:添加数据库驱动依赖
以 MySQL 为例,如果你使用 Maven,在 pom.xml 中添加依赖:

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version> <!-- 建议使用较新版本 -->
</dependency>
编写 Java 代码
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
// 1. 定义一个与 users 表对应的 Java 实体类
class User {
private int id;
private String name;
private String email;
private int age;
// 构造方法、Getter 和 Setter
public User() {}
public User(int id, String name, String email, int age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
// Getter 和 Setter 方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
public class JdbcSelectExample {
// 数据库连接信息 (请根据你的实际情况修改)
private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public static void main(String[] args) {
List<User> users = selectAllUsers();
for (User user : users) {
System.out.println(user);
}
}
/**
* 查询所有用户
* @return 用户列表
*/
public static List<User> selectAllUsers() {
List<User> userList = new ArrayList<>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "SELECT id, name, email, age FROM users";
try {
// 1. 加载驱动 (对于新版JDBC驱动,这步通常可以省略)
// Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获取连接
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// 3. 创建 PreparedStatement (推荐使用,可以防止SQL注入)
pstmt = conn.prepareStatement(sql);
// 4. 执行查询
rs = pstmt.executeQuery();
// 5. 遍历结果集
while (rs.next()) {
// 通过列名获取数据,更健壮,不易因列顺序改变而出错
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
int age = rs.getInt("age");
// 创建 User 对象并添加到列表
User user = new User(id, name, email, age);
userList.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6. 关闭资源 (非常重要!)
try {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return userList;
}
}
关键点解释:
Connection:代表与数据库的连接。PreparedStatementvsStatement:Statement:用于执行静态 SQL 语句。不推荐,因为它容易受到 SQL 注入攻击。PreparedStatement:是Statement的子接口,SQL 语句可以带参数(用 占位符),可以防止 SQL 注入,并且对于多次执行的相似 SQL,数据库可以进行预编译,性能更高。强烈推荐使用PreparedStatement。
ResultSet:代表查询结果集,它像一个指向数据行的游标。rs.next()将游标移动到下一行,如果存在下一行则返回true。rs.getXXX():XXX是数据类型(如String,Int,Date等),可以使用列名或列索引来获取值,使用列名是更好的实践。try-finally或try-with-resources:数据库连接等资源非常宝贵,必须在使用后关闭。try-with-resources是 Java 7 引入的语法,可以自动关闭实现了AutoCloseable接口(如Connection,PreparedStatement,ResultSet)的资源,代码更简洁、安全。
使用 MyBatis 框架 (主流、高效)
MyBatis 将 SQL 语句与 Java 代码分离,通过 XML 或注解配置,让开发者只需关注 SQL 本身和对象映射。
完整示例:查询用户列表
准备工作:添加 MyBatis 依赖

在 pom.xml 中添加 MyBatis 和 MySQL 驱动的依赖:
<dependencies>
<!-- MyBatis 核心库 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 日志实现,方便调试 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
配置 MyBatis
在 src/main/resources 目录下创建 mybatis-config.xml 文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 1. 设置别名,方便在 Mapper 中使用 -->
<typeAliases>
<typeAlias type="com.example.User" alias="User"/>
</typeAliases>
<!-- 2. 配置环境,比如开发环境、测试环境 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="your_username"/>
<property name="password" value="your_password"/>
</dataSource>
</environment>
</environments>
<!-- 3. 映射 Mapper 文件 -->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
创建 Mapper 接口
在 src/main/java 下创建一个 Mapper 接口,它定义了要执行的 SQL 操作。
package com.example;
import java.util.List;
public interface UserMapper {
// 方法名对应 SQL 的 id,返回值类型对应 SQL 的 resultType
List<User> selectAllUsers();
}
创建 Mapper XML 文件
在 src/main/resources 下创建 mappers 目录,并在其中创建 UserMapper.xml 文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.UserMapper">
<!-- id 必须与 Mapper 接口中的方法名完全一致 -->
<!-- resultType 指定返回的 Java 对象类型 -->
<select id="selectAllUsers" resultType="User">
SELECT id, name, email, age
FROM users
</select>
</mapper>
编写 Java 代码进行查询
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyBatisSelectExample {
public static void main(String[] args) {
// 1. 读取 MyBatis 配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
// 2. 构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3. 从 SqlSessionFactory 中获取 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
// 4. 获取 Mapper 接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
// 5. 调用 Mapper 方法,MyBatis 会自动执行对应的 SQL
List<User> users = userMapper.selectAllUsers();
// 6. 处理结果
for (User user : users) {
System.out.println(user);
}
}
}
}
MyBatis 的优势:
- 关注点分离:SQL 和 Java 代码分离,结构清晰。
- 强大的映射能力:可以轻松处理复杂的对象关系(如一对一、一对多)。
- 动态 SQL:可以方便地在 XML 中拼接 SQL 语句(如
if,where,foreach标签)。 - 性能好:有内置的一级和二级缓存机制。
总结与对比
| 特性 | 原生 JDBC | MyBatis / JPA |
|---|---|---|
| 易用性 | 低:需要编写大量模板代码(获取连接、关闭资源等) | 高:代码简洁,专注于业务逻辑 |
| 灵活性 | 极高:可以执行任何复杂的 SQL,对 SQL 的控制力最强 | 高:通过 XML 或注解配置,能满足绝大多数需求 |
| SQL 与代码耦合 | 高:SQL 语句直接写在 Java 代码中 | 低:SQL 通常配置在 XML 文件中,实现解耦 |
| 性能 | 取决于开发者,写得好性能就好 | 有缓存等优化机制,性能稳定且优秀 |
| 适用场景 | 简单的、一次性的脚本;对性能要求极高且需要极致优化的场景;学习数据库原理 | 绝大多数企业级应用,特别是项目复杂、团队协作多的场景 |
给新手的建议:
- 先理解 JDBC:虽然不推荐在实际项目中直接使用,但学习 JDBC 是理解 Java 数据库操作原理的基础。
- 直接上手 MyBatis:对于绝大多数项目,MyBatis 是更现代、更高效、更易维护的选择,它能够让你将精力更多地放在业务逻辑上,而不是繁琐的 JDBC 细节上,如果你喜欢更彻底的面向对象,也可以学习 JPA (如 Hibernate)。
