千家信息网

如何理解Spring Data JPA查询方式及方法名查询规则

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章给大家介绍如何理解Spring Data JPA查询方式及方法名查询规则,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Spring Data JPA查询方式及方法名查询规
千家信息网最后更新 2026年11月03日如何理解Spring Data JPA查询方式及方法名查询规则

这篇文章给大家介绍如何理解Spring Data JPA查询方式及方法名查询规则,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

Spring Data JPA查询方式及方法名查询规则

Spring Data JPA

一、通过解析方法名创建查询

在执行查询时,Spring Data JPA框架会把方法名进行解析,解析到前缀比如 get、getBy、find、findBy、read、readBy时,会先把这些前缀截取掉,然后对剩下部分进行解析,剩下部分分为两种:一是只有属性名,二是属性名+条件;条件很好解析,解析的关键在于属性名,下面拿一个具体的例子来帮助大家更好的理解属性名解析规则。

解析规则例子:比如实体为Product,方法为findByGoodsTypeDetail ();

1、首先截取掉 findBy,然后对剩下的属性进行解析;

2、先判断 goodsTypeDetail(根据 POJO 规范,首字母变为小写,下同)是否为 Product的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第三步;

3、从右往左截取第一个大写字母开头的字符串(本方法为 Detail),然后对比剩下的字符串(本方法为goodsType)是否为 Product的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第三步,继续从右往左截取(此处为TypeDetail,剩下goods),就这样一直循环到最终;假设 goods为 Product的一个属性,则说明goods不是常量类型,而是一个对象类型;

4、此时剩下字符串 TypeDetail,先判断goods对象中是否有 typeDetail属性,如果有,则表示该方法最终是根据 "Product.goods.typeDetail" 的值进行查询;如果没有该属性,则继续按照第三步的规则从右往左截取,最终表示根据 "Product.goods.type.detail" 的值进行查询。

不过这种解析规则不是完美的,也存在bug,不注意可能会掉到这个坑里,比如Product中有一个属性叫goods,同时还有一个属性叫goodsType,这时在解析时会出现混乱,不过可以在属性之间加上 "_"来解决这个问题,注意:"_"是加在查询方法上的,不是加在属性名上的;比如 "findByGoods_TypeDetail()" (当Product中不存在goods_TypeDetail时,是给解析器说明Goods为一个对象)或"findByGoodsType_Detail()"(当Product中不存在goodsType_Detail时,是给解析器说明GoodsType为一个对象)。

查询时,很多时候需要同时使用多个属性进行查询,而且查询的条件也各不相同,Spring Data JPA 为此提供了一些条件查询的关键字,我把常用的都整理了一下,如下表:

关键字

对应SQL关键字

示例

列名

根据列名查询

findByName(String name);自动解析findBy后面的列名,然后根据列名查询。

In

等价于SQL 中的 in

findByNameIn(Collection nameList) ;参数可以是集合、数组、不定长参数;

Like

等价于SQL 中的 like

findByNameLike(String name);

NotLike等价于SQL 中的 not likefindByNameNotLike(String name);

And

等价于SQL 中的 and

findByNameAndPwd(String name, String pwd);

Or

等价于SQL 中的 or

findByIdOrCode(String id, String code);

Between

等价于SQL 中的 between

findByNumBetween(int max, int min);

OrderBy

等价于SQL 中的 order by

findByNameOrderByNumAsc(String name);

IsNull

等价于SQL 中的 is null

findByNameIsNull();

IsNotNull等价于SQL 中的 is not nullfindByNameIsNotNull();
NotNull等价于SQL 中的 is not nullfindByNameNotNull();--和IsNotNull 一样,建议使用IsNotNull
Not等价于SQL 中的 ! =findByNameNot(String name);
NotIn等价于SQL 中的 not infindByNameNotIn(Collection nameList) ;参数可以是集合、数组、不定长参数;
LessThan等价于SQL 中的 <findByNumLessThan(int num);

GreaterThan

等价于SQL 中的 >

findByNumGreaterThan(int num);

二、使用 @Query 创建查询

1、使用 @Query 提供的位置编号查询:格式为":位置编号",然后方法中的参数按 JPQL 查询语句的位置编号顺序书写。 如下:

public interface ProductDao extends Repository {  @Query("select * from Product p where p.id= ?1") public Product findById(Long id);  @Query("select * from Product p where p.type = ?1 and p.name =?2") public Page findByTypeAndName(     Integer type,String name,Pageable pageable); }

2、使用@Query 命名参数查询:格式为": 变量",同时在方法的参数前面使用 @Param 将方法参数与JPQL中的命名参数对应。如下:

public interface ProductDao extends Repository {  @Query("from Product p where p.goodsName= :name") public Product findByGoodsName(@Param("name")String name);  @Query("from Product p where p.num < :num") public Page findByNumLessThan(     @Param("num")Integer num,Pageable pageable); }

3、 使用 @Modifying 将查询操作标识为更新操作:在使用 @Query 的同时使用 @Modifying ,这样会生成一个更新的操作,而非查询。如下:

 @Query("update Product p set p.name = ?1 where p.id = ?2") @Modifying public int updateName(String name, int id);

JPA 常用查询方法记录

以这张表为例:

+-------------+--------------+------+-----+-------------------+----------------+| Field       | Type         | Null | Key | Default           | Extra          |+-------------+--------------+------+-----+-------------------+----------------+| id          | int(11)      | NO   | PRI | NULL              | auto_increment || role        | varchar(45)  | NO   |     | NULL              |                || permissions | varchar(512) | NO   |     | NULL              |                || create_time | datetime     | NO   |     | CURRENT_TIMESTAMP |                || status      | varchar(45)  | NO   |     | NULL              |                || role_name   | varchar(45)  | NO   |     | NULL              |                |+-------------+--------------+------+-----+-------------------+----------------+

CrudRepository 默认带的查询方法

@Repositorypublic interface RoleRepository extends CrudRepository {}  @Entity@Table(name = "role", catalog = "message_push")public class RoleData implements java.io.Serializable {     @Id    @GeneratedValue    private Integer id;     private String role;     private String permissions;     private Long create_time;     private Integer status; // getter setter 构造函数从略 }

简单的扩展-以字段为关键字进行查询

list findByXXX(xxx) 其中 XXX 对应数据库中的字段,例如:

@Repositorypublic interface RoleRepository extends CrudRepository {     List findByRole(String role);    List findByStatus(String status);}

还可以多字段AND 查询:

@Repositorypublic interface RoleRepository extends CrudRepository {     List findByRoleAndStatus(String role, String status);}

在 application.properties 中加入以下配置 spring.jpa.show-sql=true 可以看到SQL语句:

Hibernate: select roledata0_.id as id1_0_, roledata0_.create_time as create_t2_0_, roledata0_.permissions as permissi3_0_, roledata0_.role as role4_0_, roledata0_.status as status5_0_ from message_push.role roledata0_ where roledata0_.role=? and roledata0_.status=?

当然 or 也是可以:

List findByRoleOrStatus(String role, String status);

Hibernate: select roledata0_.id as id1_0_, roledata0_.create_time as create_t2_0_, roledata0_.permissions as permissi3_0_, roledata0_.role as role4_0_, roledata0_.status as status5_0_ from message_push.role roledata0_ where roledata0_.role=? or roledata0_.status=?

使用@Query 进行复杂查询

例如:

@Query(value = "select * from role where role = ?1", nativeQuery = true)List searchByRole(String role);

或 sql in 用法

@Query(value = "select * from role where role in (?1) and status = 'valid'", nativeQuery = true)List searchByRoleList(List targetList);

又或 sql like 用法:

@Query(value = "select * from role where role like %?1%", nativeQuery = true)List searchByRole(String keyWord);

使用 Specification 进行复杂查询

先来看一下 JpaSpecificationExecutor 接口

以 findAll(Specification) 为例进行说明:

Specification 可以理解为一个查询条件。findAll 以这个条件为基准进行查询,也就是我们在sql 里写的 whre xxx 转为 Specification 来写。

首先要让我们的 repository 继承 JpaSpecificationExecutor

@Repositorypublic interface RoleRepository extends CrudRepository, JpaSpecificationExecutor {

接下来,将这个查询 [ select * from role where role like '%a%' ] 转为一个简单的 Specification。

final Specification spec = new Specification () {            @Override            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {                Predicate predicate = criteriaBuilder.like(root.get("role"), "%a%");                return predicate;            }        };

然后直接按如下方式调用即可:

roleRepository.findAll(spec);

Specification 里又衍生出了好几个类,分别介绍一下:

Predicate

因为我们实现 Specification 接口时,只需要实现 Predicate toPredicate() 方法。而 Specification 上文中我们当做搜索条件来理解了,那么也可以简单的把 Predicate 视为搜索条件。

CriteriaBuilder

用于构建搜索条件 Predicater 的。

回想一下SQL搜索条件怎么写

where attribute = xxwhere attribute > xx where attribute < xxwhere attribute like %xx%

注意这里有三要素:

  • attribute 搜索指定的数据库字段

  • 操作符 大于 小于 等于

  • 具体数据

CriteriaBuilder提供了一系列静态方法构建这三要素。

比如

  • CriteriaBuilder.like(数据库字段, 具体数据)

  • CriteriaBuilder.equal(数据库字段, 具体数据)

其中 数据库字段 不能直接写字符串,需要下一个工具类 Root 的 get 方法获取。

Root

root.get( String attributeName ) 参数 attributeName 就是数据库里的字段名

现在相信读者可以理解 我们刚才写的 那个完整的 Specification了。

再下来再上一个稍微复杂点的例子:

[  select * from role where role like '%a%' and (id > 11 or id < 8) ]
final Specification spec = new Specification () {            @Override            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {                Predicate roleLikeaPredicate = criteriaBuilder.like(root.get("role"), "%a%");                Predicate idLessThan8Predicate = criteriaBuilder.lessThan(root.get("id"), 8);                Predicate idGreaterThan12Predicate = criteriaBuilder.greaterThan(root.get("id"), 11);                 Predicate idCombindedPredicate = criteriaBuilder.or(idLessThan8Predicate, idGreaterThan12Predicate);                Predicate predicate = criteriaBuilder.and(idCombindedPredicate, roleLikeaPredicate);                 return predicate;            }        };

其实也很简单,就是多了 criteriaBuilder.or criteriaBuilder.and 来把多个 Predicate 合成一个新的 Predicate

最后一个例子:

可以通过root.get(xx).in(List<> list) 也是可以直接返回 Predicate 的

         final Specification spec2 = new Specification () {            @Override            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {                List alist = new ArrayList();                alist.add("admin");                Predicate predicate = root.get("role").in(alist);                return predicate;            }        };

关于如何理解Spring Data JPA查询方式及方法名查询规则就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

查询 属性 方法 等价 参数 条件 数据 字段 规则 数据库 关键 搜索 方式 例子 关键字 同时 字符 字符串 对象 复杂 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 小米移动互联网科技园 博彦科技互联网金融 科技信息互联网 互联网科技未来 科技制造互联网公司 互联网 卓越科技 苏州互联网科技贷款公司 互联网科技ppt模板 时间互联网络科技 科技互联网创业计划书 天扬科技互联网广告 深圳卡尔迅互联网科技有限公司怎么样 成都互联网科技公司100强 深圳市优智互联网科技有限公司 互联网科技大奖都有哪些公司 亳州好赞互联网科技有限公司 保险科技服务互联网营销体系 互联网科技平台产品运营 互联网科技职业技能培训学校 米泉互联网科技专业怎么样 精品咖啡豆 广东万易互联网科技有限公司惠州分公司 互联网科技有限公司经营范围 互联网金融 科技金融 广州宏创互联网科技 无线互联网科技 易通互联网络科技有限公司 互联网科技公司需要的职位 群盈汇互联网科技有限公司 下一代互联网重大应用科技园
0