Spring Data JPA Repository接口必须继承JpaRepository等规范接口,方法名须以find/read/query/count/exists开头,实体需有@Entity和@Id,字段名须与实体属性完全一致,返回值永不为null(除自定义单对象查询外)。

Repository接口怎么写才不会报错
Spring Data JPA 的 Repository 接口本身不实现,靠代理生成,所以不能随便继承或加方法——必须严格遵循规范。
- 必须继承
JpaRepository<Entity, ID>或其子接口(如CrudRepository、PagingAndSortingRepository),不能只写空接口 - 自定义方法名必须以
find、read、query、count、exists开头,否则启动时直接抛IllegalArgumentException: Failed to create query for method... - 实体类必须有
@Entity且主键字段标了@Id,否则JpaRepository找不到 ID 类型,运行时报Unable to locate Attribute with the given name - 接口不能是
public abstract class,也不能带implements,只能是public interface
方法名推导查询为什么查不到数据
名字写对了,SQL 也生成了,但返回空集合?大概率是字段名、大小写或关联路径没对上。
- 方法名中的属性名必须和实体类字段名**完全一致**(不是数据库列名),比如实体里是
userName,就不能写findByUsername—— 除非你加了@Column(name = "username")并启用了spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy - 嵌套属性要用
.连接,如findByAuthor_Name对应author.name字段,但author必须是实体里的@ManyToOne关联字段,且不能是懒加载未初始化状态(否则可能 NPE) - 关键词大小写敏感:
findByStatusIn和findByStatusNotIn是不同语义;Containing等价于LIKE %?%,而Like是LIKE ?,别混用 - 如果用了
@Query覆盖默认推导,记得检查 JPQL 是否写成 SQL(JPQL 操作的是类和属性,不是表和字段)
什么时候该放弃方法名推导,改用 @Query
推导适合简单条件,一旦涉及多表 JOIN、聚合函数、复杂 OR 条件或数据库特有语法,硬凑方法名反而难读易错。
- 需要 LEFT JOIN 关联查询时,推导不支持
fetch+join组合,必须用@Query("SELECT DISTINCT u FROM User u LEFT JOIN FETCH u.roles WHERE ...") - 要查 COUNT 但又不想绕开分页逻辑,
countByXxx只能返回 long,没法复用同一套 where 条件,不如写两个@Query:一个带count,一个带select - 使用 PostgreSQL 的
ILIKE、MySQL 的REGEXP等特性时,推导无法生成,必须手写原生 SQL 并设nativeQuery = true - 参数顺序容易乱:推导方法的参数顺序必须严格对应方法名中条件出现的顺序;
@Query用@Param显式命名更稳
findBy… 方法返回 null 还是空集合
findOptionalBy… 返回 Optional,其它所有 find… 方法(包括 findAll)都返回集合,**永远不会返回 null** —— 这是 Spring Data JPA 的契约,也是很多人踩坑的起点。
立即学习“Java免费学习笔记(深入)”;
-
findOneById(id)已废弃,用findById(id),它返回Optional<Entity>;若想直接取值,别裸调.get(),先判isPresent() -
findByXxx(...)查不到就是空List,可直接用list.isEmpty()判断,不用防 null - 但注意:如果你写了
@Query并设了optional = true,返回类型就得是Optional<Entity>,否则运行时报java.lang.IllegalStateException: Optional parameter 'xxx' is not supported - 自定义查询方法若返回单个对象(如
findTop1ByStatusOrderByCreateTimeDesc),查不到时返回null,不是空集合 —— 这点和批量查询不一致,得单独处理
JPA 的方法名推导看着省事,实际最麻烦的是字段映射一致性、大小写、嵌套路径这些隐性约束。写完别急着跑,先看下日志里打印的 SQL 对不对,比猜强得多。










