Spring Data JPA实战:从入门到精通
·
面向接口编程的 ORM:从基础到实战
一、面向接口编程的 ORM
定义
ORM(Object-Relational Mapping,对象关系映射)是一种将 Java 对象与数据库表之间进行自动映射的技术。JPA(Java Persistence API)是 Java 官方定义的一套 ORM 规范,而 Spring Data JPA 则是对 JPA 进行了进一步的封装和增强,提供了更便捷的开发体验。
核心思想:让 Java 对象和数据库表自动对应起来,你操作对象,框架帮你操作数据库。


核心三要素
| 组件 | 作用 | 示例 |
|---|---|---|
@Entity |
标记 Java 类为数据库表映射 | @Entity @Table(name = "user") public class User { ... } |
Repository |
数据访问接口(继承 JpaRepository<T, ID>) |
public interface UserRepository extends JpaRepository<User, Long> {} |
| Query Methods | 方法名自动解析为 SQL | List<User> findByEmailAndStatus(String email, String status); |
二、Query Methods:方法名即查询
原理
Spring Data JPA 在启动时会扫描 Repository 接口,根据方法名按规则生成 JPQL/HQL 查询。例如:
findByXxx→WHERE xxx = ?findByXxxIgnoreCase→ 忽略大小写findByXxxOrderByYyyDesc→ 自动加ORDER BY yyy DESC
示例
// Entity 类
@Entity
@Table(name = "user")//指定数据库表名
@Data // Lombok 自动生成 getter/setter/toString
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键
private Long id;
private String userName;
private String email;
private String status;
}
// Repository 接口
public interface UserRepository extends JpaRepository<User, Long> {
// 根据邮箱和状态查询用户
List<User> findByEmailAndStatus(String email, String status);
// 忽略大小写的邮箱查询
List<User> findByEmailIgnoreCase(String email);
// 按用户名降序排序
List<User> findByStatusOrderByUserNameDesc(String status);
}
复杂查询
对于复杂的查询需求,建议使用 @Query 注解来编写原生 SQL 或 JPQL,避免方法名过长且难以维护。
public interface UserRepository extends JpaRepository<User, Long> {
// 使用 @Query 编写复杂查询
@Query("SELECT u FROM User u WHERE u.email LIKE %:email% AND u.status = :status")
List<User> findUsersByEmailLike(@Param("email") String email, @Param("status") String status);
}
常用注解(新手速查)
| 注解 | 是否必须 | 典型用法 | 说明 |
|---|---|---|---|
@Entity |
✅ 必须 | 类上 | 标记为实体 |
@Id |
✅ 必须 | 主键字段 | 标记主键 |
@GeneratedValue |
✅ 主键通常需要 | 主键字段 | 自动生成主键值 |
@Table |
❌ 可选 | 类上 | 指定表名 |
@Column |
❌ 可选 | 字段上 | 指定列名或加约束 |
@Transient |
❌ 可选 | 字段上 | 排除字段不映射 |
三、动手实践:从零开始构建一个简单的 JPA 应用
1. 引入依赖
首先,在 pom.xml 中添加 Spring Boot 和 JPA 的依赖:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok for reducing boilerplate code -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2. 配置数据源
在 application.yml 中配置数据库连接信息:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
username: root
password: your-password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update # 自动创建和更新表结构
show-sql: true # 打印生成的 SQL
3. 创建实体类
import lombok.Data;
import javax.persistence.*;
@Entity
@Table(name = "user")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_name", nullable = false, length = 100)//描述字段如何映射到列,大多数情况可以省略(靠命名进行约定),除了列名不等于驼峰命名转换或者需要加约束
private String userName;
@Column(nullable = false, unique = true)
private String email;
private String status;
}
4. 创建 Repository 接口
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByEmailAndStatus(String email, String status);
List<User> findByEmailIgnoreCase(String email);
List<User> findByStatusOrderByUserNameDesc(String status);
}
5. 创建 Service 层
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getUsersByEmailAndStatus(String email, String status) {
return userRepository.findByEmailAndStatus(email, status);
}
public List<User> getUsersByEmailIgnoreCase(String email) {
return userRepository.findByEmailIgnoreCase(email);
}
public List<User> getUsersByStatusOrderByUserNameDesc(String status) {
return userRepository.findByStatusOrderByUserNameDesc(status);
}
}
6. 创建 Controller 层
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public List<User> getUsers(
@RequestParam(required = false) String email,
@RequestParam(required = false) String status) {
if (email != null && status != null) {
return userService.getUsersByEmailAndStatus(email, status);
} else if (email != null) {
return userService.getUsersByEmailIgnoreCase(email);
} else if (status != null) {
return userService.getUsersByStatusOrderByUserNameDesc(status);
} else {
return userService.getUsersByStatusOrderByUserNameDesc("ACTIVE");
}
}
}
四、总结
- ORM 的核心概念:如何通过对象关系映射(ORM)简化数据库操作。
- JPA 和 Spring Data JPA 的使用:如何使用注解和方法名自动生成查询。
- 实际项目中的应用:从零开始构建一个简单的 JPA 应用,并展示了如何通过
@Entity、Repository和Service实现 CRUD 操作。
最后
- 保持命名一致性:尽量让数据库字段名符合“下划线命名”规则(如
user_name),Java 字段名使用驼峰命名(如userName)。这样可以减少不必要的@Column注解。 - Lombok 简化代码:使用
@Data注解可以自动生成 getter/setter/toString 方法,减少样板代码。 - 合理使用
@Query:对于复杂的查询需求,使用@Query编写原生 SQL 或 JPQL,避免方法名过长且难以维护。
更多推荐




所有评论(0)