JDBC, JPA, ORM Hibernate
1. JDBC vs MySQL Connector#
JDBC(Java Database Connectivity)是 Java 访问数据库的最底层标准规范和 API。它提供了连接数据库、执行 SQL、获取结果集等核心功能。
后面提到的 MyBatis、Hibernate、Spring Data JPA 都是基于 JDBC 来执行底层 SQL 操作的。
可以直接编写 SQL、使用
PreparedStatement
等 API 来执行操作。
Sometimes, I always mistake MySQL driver for JDBC, a little funny, lol. JDBC is part of JDK, which is java’s standard library, like code belowjava.sql.*
belongs to Java SE API, which is also called JDBC API.
We often add com.mysql.cj.jdbc.Driver
dependency to our maven project. Actually com.mysql.cj.jdbc.Driver
is MySQL Connector.
package database;
// java.sql.* 属于 Java SE API, 这就是 JDBC API
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class MysqlDatabase {
@Override
public Connection connect() throws SQLException {
// You must load jdbc driver, otherwise you will get null for connection.
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(this.url, this.user, this.password);
}
}
As shown above java.sql.SQLException
and java.sql.Connection
are all belong to java.sql.*
which is part of java se api, namely, JDBC. So we don’t commucate with MySQL database with MySQL Connector directly, actually, we conmmucate with MySQL(retrive & insert data) by “talking” to JDBC API, then JDBC API commucate with MySQL Connector, and MySQL Connector commucate with MySQL database.
2. JPA (Jakarta Persistence API)#
JPA 只是一个规范, 它定义了一套接口和注解体系,比如 @Entity
, @Table
, @Id
, @Column
等。
JPA 的实现:要想让 JPA 的接口和注解真的“跑起来”,就需要有一个具体的实现类库(provider)
- Hibernate 是 JPA 的一个实现。它负责解析 JPA 的注解,并执行具体的 ORM(对象关系映射)逻辑,比如生成 SQL 语句,管理数据库操作等。JPA 只是定义规则,而 Hibernate 负责执行。 如果没有 JPA 的实现,
@Entity
等注解就没有意义 - OpenJPA(Apache 的实现)
Spring Data JPA 是 基于 JPA 规范 的一个 Spring 生态组件,它简化了 JPA 的使用,比如提供了 JpaRepository
让你不用手写 SQL 查询。Spring Data JPA 仍然需要 JPA Provider(比如 Hibernate) 来执行实际的数据库操作。Spring Data JPA 本身不是 ORM 框架,它只是对 JPA 进行了封装,使得 JPA 的使用更方便。
MyBatis 是一款半 ORM / 数据映射(Data Mapper)框架,与传统的 JDBC 相比更灵活且简化了数据访问的过程,但不像 Hibernate 那样做全量的实体与表的自动映射
MyBatis 不是 JPA 实现,而是另一种独立的 ORM 方案,不能用来替代 Hibernate,但可以在项目中和 JPA 共同使用(比如复杂查询用 MyBatis,简单增删改查用 JPA)
3. Spring Data JPA + JPA + Hibernate 各司其职#
3.1. JPA(Model 层)#
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// nullable = false 在 Java 层面防止错误数据进入数据库,即使数据库层面有 NOT NULL 约束
@Column(nullable = false, unique = true, length = 50)
private String username;
}
@Entity
:标明该类是 JPA 实体@Table(name = "users")
:指定数据库表名@Id
、@GeneratedValue
:定义主键及其生成策略@Column
:指定字段约束这里
@Entity
和@Table
等是 JPA 规范的一部分,它们只是 告诉 JPA Provider(比如 Hibernate),这个类需要映射到数据库表。但真正解析这些注解并生成 SQL 语句的是 Hibernate。你写的是 JPA 代码,但实际 SQL 是 Hibernate 生成的, JPA 只定义规则,Hibernate 负责执行
3.2. Spring Data JPA(Repository 层)#
Spring Data JPA 让我们可以不写 SQL 也能操作数据库:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
...
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
// 查找用户的所有帖子
@Query("SELECT p FROM Post p WHERE p.userId = :userId AND p.status = 1")
Page<Post> findByUserId(@Param("userId") Long userId, Pageable pageable);
// 查找所有正常状态的帖子(分页)
@Query("SELECT p FROM Post p WHERE p.status = 1")
Page<Post> findAllActivePosts(Pageable pageable);
}
@Query
、@Param
、JpaRepository
、Pageable
等注解和接口都是 Spring Data JPA 提供的,而不是 标准 JPA(Jakarta Persistence API) 或 Hibernate 本身的一部分这些方法 不需要手动实现,Spring Data JPA 会自动生成对应的 SQL 语句并执行,你只需要声明方法即可直接调用
@Query
可以优化掉,让 Spring Data JPA 自动生成 SQL 语句, Spring Data JPA 会 自动解析方法名 生成 SQL 查询, 上面代码可以改成:
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
// 查找用户的所有正常状态帖子
Page<Post> findByUserIdAndStatus(Long userId, int status, Pageable pageable);
// 查找所有正常状态的帖子
Page<Post> findByStatus(int status, Pageable pageable);
}
如果查询逻辑 复杂,Spring Data JPA 无法自动推断,就需要 @Query
,比如:
@Query("SELECT p FROM Post p WHERE p.userId = :userId AND p.status = 1 ORDER BY p.createdAt DESC")
List<Post> findRecentPostsByUser(@Param("userId") Long userId);
3.3. Hibernate(持久化层)#
Hibernate 作为 JPA Provider,在后台实际执行 SQL 语句, 当我们调用 userRepository.findByEmail("[email protected]")
时,Hibernate 会生成 SQL 查询:
SELECT * FROM users WHERE email = 'test@example.com' LIMIT 1;
4. Spring Data JPA + JPA + Hibernate#
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
这里 findByEmail(String email)
方法没有实现,为什么它还能执行数据库查询呢?这是 Spring Data JPA + JPA + Hibernate 三者协作的结果, 当你调用:
Optional<User> user = userRepository.findByEmail("[email protected]");
Spring Data JPA、JPA(EntityManager)和 Hibernate 会分别执行自己的工作:
1️⃣ Spring Data JPA(提供 Repository 代理)
Spring Data JPA 看到 UserRepository
继承了 JpaRepository
,就会:
- 自动生成
findByEmail
方法的实现 - 调用 JPA 的
EntityManager
API 进行查询
📌 这里的关键点:
- 你没有手写 SQL,但 Spring Data JPA 根据方法名 解析出查询意图
- 它会调用 JPA(EntityManager) 来执行查询
2️⃣ JPA(EntityManager 提供查询 API)
Spring Data JPA 内部会使用 JPA 的 EntityManager
执行查询:
entityManager.createQuery("SELECT u FROM User u WHERE u.email = :email", User.class);
📌 JPA(EntityManager)在这里的角色:
- 提供 API 让 Spring Data JPA 调用(比如
createQuery()
) - 不会解析和执行 SQL,它只是 JPA 标准的实现者
3️⃣ Hibernate(JPA Provider 解析 & 执行 SQL)
Hibernate 作为 JPA Provider,接手 EntityManager
提供的查询请求,并执行 SQL:
-
解析 JPQL:
SELECT u FROM User u WHERE u.email = :email
-
转换成原生 SQL(针对 MySQL、PostgreSQL 等数据库生成 SQL):
SELECT * FROM users WHERE email = '[email protected]' LIMIT 1;
-
执行 SQL,从数据库查询结果,并返回
User
实例。
📌 Hibernate 负责的部分:
- 解析 JPA 的查询语法(JPQL)
- 生成 SQL 并执行
- 把数据库查询结果转换成 Java 对象
完整流程总结
步骤 | 执行者 | 作用 |
---|---|---|
1 | Spring Data JPA | 解析 findByEmail 方法,调用 EntityManager |
2 | JPA(EntityManager) | 负责 API 调用,准备 JPQL 查询 |
3 | Hibernate | 解析 JPQL,转换为 SQL,并执行查询 |
4 | 数据库 | 运行 SQL,返回数据 |
5 | Hibernate | 解析 SQL 结果,转换成 User 对象 |
6 | Spring Data JPA | 返回 User 对象给调用者 |
总结
- Spring Data JPA 让你不用手写 SQL,直接调用
JpaRepository
方法 - JPA(EntityManager) 只是提供 API,不会执行 SQL
- Hibernate 作为 JPA Provider,负责执行 SQL,并转换结果
💡 最终的 SQL 查询是 Hibernate 负责执行的,Spring Data JPA 和 JPA 只是提供 API 和接口,真正的数据库操作全靠 Hibernate。