目录
前言
一、JPA 核心概念与实体映射
1. 什么是 JPA?
2. JPA 的主要组件
3. 实体映射
4. 常见的字段映射策略
二、Repository 接口与自定义查询
1. 什么是 Repository 接口?
2. 动态查询方法
3. 自定义查询
4. 分页与排序
三、实战案例:完整数据持久化示例
1. 创建一个简单的用户管理系统
2. 测试接口
前言
在现代企业级应用开发中,数据持久化是不可或缺的一部分。Spring Boot 提供了对 JPA(Java Persistence API)的强大支持,使得数据库操作变得更加简单和高效。本文将从以下几个方面详细讲解如何在 Spring Boot 中整合 JPA 实现数据持久化:
- JPA 核心概念与实体映射
- Repository 接口与自定义查询
通过本文的学习,你将能够掌握 Spring Boot 中 JPA 的基本使用方法,并能够根据实际需求进行灵活的扩展。
一、JPA 核心概念与实体映射
1. 什么是 JPA?
JPA(Java Persistence API)是 Java EE 平台中用于对象关系映射(ORM)的标准 API。它允许开发者通过 Java 类来表示数据库中的表,并通过 JPA 提供的接口和注解来执行 CRUD(增删改查)操作。
2. JPA 的主要组件
- EntityManager:负责管理实体对象的生命周期,并提供 CRUD 操作的方法。
- Persistence Unit:一组相关的实体类和配置信息的集合。
- Entity:表示数据库表的 Java 类。
3. 实体映射
在 JPA 中,实体类通过注解来映射到数据库表。以下是常用的注解:
@Entity
:标识这是一个实体类。@Table
:指定实体类对应的数据库表名。@Id
:标识实体类的主键字段。@GeneratedValue
:指定主键的生成策略。@Column
:指定字段对应的数据库列名、长度等属性。
示例代码:
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", length = 50, nullable = false)
private String username;
@Column(name = "email", unique = true)
private String email;
// Getter and Setter methods
}
4. 常见的字段映射策略
- 基本类型映射:如
String
、Integer
、Long
等。 - 关联关系映射:
- 一对一(OneToOne):通过
@OneToOne
注解实现。 - 一对多(OneToMany):通过
@OneToMany
注解实现。 - 多对一(ManyToOne):通过
@ManyToOne
注解实现。 - 多对多(ManyToMany):通过
@ManyToMany
注解实现。
- 一对一(OneToOne):通过
示例代码(一对多关系):
import jakarta.persistence.*;
@Entity
@Table(name = "posts")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "title", nullable = false)
private String title;
@Column(name = "content")
private String content;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
// Getter and Setter methods
}
二、Repository 接口与自定义查询
1. 什么是 Repository 接口?
Spring Data JPA 提供了一个 Repository
接口,用于简化数据访问层的开发。通过继承 JpaRepository
或 CrudRepository
,我们可以快速获得 CRUD 操作的能力。
示例代码:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
JpaRepository
:继承了CrudRepository
和PagingAndSortingRepository
,提供了基本的 CRUD 操作和分页支持。UserRepository
:定义了一个针对User
实体的仓库接口。
2. 动态查询方法
Spring Data JPA 支持通过方法名动态生成查询语句。例如:
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByUsername(String username);
List<User> findByEmailContaining(String keyword);
List<User> findByUsernameAndEmail(String username, String email);
}
findByUsername
:根据用户名查询用户。findByEmailContaining
:根据邮箱包含关键字查询用户。findByUsernameAndEmail
:根据用户名和邮箱联合查询用户。
3. 自定义查询
对于复杂的查询需求,可以通过 @Query
注解来自定义 JPQL(Java Persistence Query Language)或原生 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;
import java.util.List;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.username LIKE %:keyword%")
List<User> findByUsernameLike(@Param("keyword") String keyword);
@Query(value = "SELECT * FROM users WHERE email LIKE %?1%", nativeQuery = true)
List<User> findByEmailLike(String keyword);
}
findByUsernameLike
:使用 JPQL 查询用户名包含关键字的用户。findByEmailLike
:使用原生 SQL 查询邮箱包含关键字的用户。
4. 分页与排序
Spring Data JPA 提供了 Pageable
接口来支持分页和排序。
示例代码:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findAll(Pageable pageable);
Page<User> findByUsernameContaining(String keyword, Pageable pageable);
}
三、实战案例:完整数据持久化示例
1. 创建一个简单的用户管理系统
实体类(User.java ):
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", length = 50, nullable = false)
private String username;
@Column(name = "email", unique = true)
private String email;
// Getter and Setter methods
}
Repository 接口(UserRepository.java ):
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;
import java.util.List;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByUsername(String username);
@Query("SELECT u FROM User u WHERE u.email LIKE %:keyword%")
List<User> findByEmailLike(@Param("keyword") String keyword);
}
Service 层(UserService.java ):
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> findAllUsers() {
return userRepository.findAll();
}
public User saveUser(User user) {
return userRepository.save(user);
}
public List<User> findByUsername(String username) {
return userRepository.findByUsername(username);
}
public List<User> findByEmailLike(String keyword) {
return userRepository.findByEmailLike(keyword);
}
}
Controller 层(UserController.java ):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.findAllUsers();
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
@GetMapping("/username/{username}")
public List<User> findByUsername(@PathVariable String username) {
return userService.findByUsername(username);
}
@GetMapping("/email/{keyword}")
public List<User> findByEmailLike(@PathVariable String keyword) {
return userService.findByEmailLike(keyword);
}
}
2. 测试接口
启动应用后,可以通过 Postman 或 Swagger UI 测试以下接口:
GET http://localhost:8080/api/users
:获取所有用户。POST http://localhost:8080/api/users
:创建新用户。GET http://localhost:8080/api/users/username/{username}
:根据用户名查询用户。GET http://localhost:8080/api/users/email/{keyword}
:根据邮箱关键字查询用户。