06.1 — Spring Data JPA
定位: Spring Data JPA Repository 接口体系与查询方式 面试高频度: ⭐⭐⭐⭐ 考查方式: 方法命名查询、@Query、JPA 核心注解
一、这是什么?为什么需要它?
Spring Data JPA 通过 Repository 接口体系,大幅减少 JPA 数据访问层的样板代码。开发者只需定义接口,Spring 自动实现 CRUD、分页、排序等操作。
二、原理拆解
2.1 Repository 接口体系
Repository<T, ID>
-> CrudRepository<T, ID>
-> PagingAndSortingRepository<T, ID>
-> JpaRepository<T, ID>
-> 自定义 UserRepository
-> SimpleJpaRepository (默认实现)2.2 方法命名查询
Spring Data JPA 根据方法名自动生成查询:
java
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastName(String lastName);
List<User> findByLastNameAndFirstName(String lastName, String firstName);
List<User> findByLastNameContaining(String keyword);
List<User> findByAgeGreaterThanOrderByAgeDesc(Integer age);
Page<User> findByActiveTrue(Pageable pageable);
long countByStatus(UserStatus status);
boolean existsByEmail(String email);
}方法命名关键字
| 关键字 | 示例 | JPQL 片段 |
|---|---|---|
| And | findByLastnameAndFirstname | where x.lastname = ?1 and x.firstname = ?2 |
| Or | findByLastnameOrFirstname | where x.lastname = ?1 or x.firstname = ?2 |
| Between | findByAgeBetween | where x.age between ?1 and ?2 |
| LessThan | findByAgeLessThan | where x.age < ?1 |
| Containing | findByNameContaining | where x.name like %?1% |
| In | findByAgeIn | where x.age in ?1 |
| OrderBy | findByAgeOrderByNameDesc | where x.age = ?1 order by x.name desc |
2.3 @Query 自定义查询
java
public interface UserRepository extends JpaRepository<User, Long> {
// JPQL 查询
@Query("SELECT u FROM User u WHERE u.email = ?1")
Optional<User> findByEmail(String email);
// 原生 SQL
@Query(value = "SELECT * FROM users WHERE status = ?1", nativeQuery = true)
List<User> findByStatus(String status);
// 更新操作
@Modifying
@Query("UPDATE User u SET u.status = ?2 WHERE u.id = ?1")
int updateStatus(Long id, String status);
}2.4 JPA 核心注解
java
@Entity // 标识为 JPA 实体
@Table(name = "users") // 指定表名
public class User {
@Id // 主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
private Long id;
@Column(name = "full_name", nullable = false)
private String name;
@Column(unique = true)
private String email;
@Enumerated(EnumType.STRING)
private UserStatus status;
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
}三、面试视角
| 追问 | 答案要点 |
|---|---|
| 方法命名查询如何自动实现? | Spring 解析方法名 -> 提取关键字 -> 生成 CriteriaQuery |
| @Modifying 的作用? | 标识更新/删除操作,自动清空持久化上下文 |
| nativeQuery = true 和 JPQL 区别? | JPQL 面向对象跨数据库,native SQL 依赖具体数据库 |
📚 相关链接
- **JPA高级与优化** — N+1 问题、关联映射、缓存
- **JdbcTemplate与多数据源** — JDBC 方式
- ← 返回 **返回 数据访问索引**