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 默认带的查询方法

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer> {
}


@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<RoleData> findByXXX(xxx) 其中 XXX 对应数据库中的字段,例如:

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer> {

    List<RoleData> findByRole(String role);
    List<RoleData> findByStatus(String status);
}

还可以多字段AND 查询:

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer> {

    List<RoleData> 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<RoleData> 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<RoleData> searchByRole(String role);

或 sql in 用法

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

又或 sql like 用法:

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

使用 Specification 进行复杂查询

先来看一下 JpaSpecificationExecutor 接口

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

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

首先要让我们的 repository 继承 JpaSpecificationExecutor

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer>, JpaSpecificationExecutor<RoleData> {

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

        final Specification<RoleData> spec = new Specification<RoleData> () {
            @Override
            public Predicate toPredicate(Root<RoleData> 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 = xx

where attribute > xx 

where attribute < xx

where 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<RoleData> spec = new Specification<RoleData> () {
            @Override
            public Predicate toPredicate(Root<RoleData> 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<RoleData> spec2 = new Specification<RoleData> () {
            @Override
            public Predicate toPredicate(Root<RoleData> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<String> alist = new ArrayList<String>();
                alist.add("admin");
                Predicate predicate = root.get("role").in(alist);
                return predicate;
            }
        };

还有很多没讲,后续有时间再补充吧。

<think>我们正在讨论JPA(JavaPersistenceAPI)中的方法命名规则查询。根据引用[1],SpringDataJPA通过方法名自动生成查询,方法名以"findBy"开头,后跟属性名(首字母大写)和条件(首字母大写)。此外,引用[5]提供了一些示例,如`findBySexOrderByName`、`findBySexOrderByNameAsc`等,展示了排序关键字的使用。JPA常用关键字列表主要包括以下几类:1.**查询关键字**:用于条件查询,如:-`And`:连接多个条件,相当于SQL中的AND。-`Or`:连接多个条件,相当于SQL中的OR。-`Is`、`Equals`:等于(通常可省略)。-`Between`:在某个范围内。-`LessThan`、`LessThanEqual`:小于、小于等于。-`GreaterThan`、`GreaterThanEqual`:大于、大于等于。-`After`、`Before`:用于日期比较(之后、之前)。-`IsNull`、`IsNotNull`:为空、不为空。-`Like`、`NotLike`:模糊匹配(区分大小写)。-`Containing`:相当于`%value%`(不区分大小写,实际生成LIKE)。-`StartingWith`、`EndingWith`:以...开头、以...结尾(生成LIKE)。-`Not`:不等于。-`In`、`NotIn`:在某个集合内、不在某个集合内。-`True`、`False`:布尔值等于true或false。-`IgnoreCase`:忽略大小写,通常用在属性名后,如`findByNameIgnoreCase`。2.**排序关键字**:用于结果排序,如:-`OrderBy`:后跟属性名和排序方向(可省略方向,默认升序)。-`Asc`:升序(可省略不写)。-`Desc`:降序。3.**分页和排序**:引用[3]提到,通过继承`PagingAndSortingRepository`接口,可以直接使用分页和排序功能,但方法名中不直接体现分页(分页通过参数传递)。排序也可以在方法名中指定(如上所述)。4.**其他关键字**:-`Distinct`:去重查询。-`First`、`Top`:限制返回结果数量,如`findFirst10By`。示例方法名:-`findByLastNameAndFirstName(StringlastName,StringfirstName)`-`findByAgeBetween(intminAge,intmaxAge)`-`findByCreateDateBefore(Datedate)`-`findByNameContaining(StringnamePart)`-`findByNameIgnoreCase(Stringname)`-`findByActiveTrue()`-`findByCategoryIn(Collection<String>categories)`-`findByOrderByAgeAsc()`-`findTop5ByOrderByScoreDesc()`注意事项:-属性名必须与实体类属性一致,且首字母大写(方法解析时会自动匹配)。-多个条件关键字组合时,按顺序对应参数。-排序关键字`OrderBy`可以出现在条件之后,多个排序字段用`And`连接(但实际用逗号分隔,方法名中写多个属性即可,如`findBySexOrderByNameAscAgeDesc`)。关于事务管理(引用[4])和面向对象特性(引用[2])虽然重要,但不在关键字列表的讨论范围内。§§相关问题§§1.JPA方法命名查询中如何处理多属性排序?2.如何实现忽略大小写的查询?3.JPA中如何实现分页查询?</think>### JPA 常用关键字列表 在 Spring Data JPA 中,方法命名规则查询通过**关键字组合**自动生成 SQL 查询。核心规则是:方法名以 `findBy`、`countBy`、`deleteBy` 等开头,后接**属性名(首字母大写) + 查询条件关键字**。以下是常用关键字分类说明: --- #### 一、基础查询关键字 | 关键字 | 示例方法名 | 等效 SQL | 说明 | |---------------|-------------------------------|-----------------------|--------------------------| | `And` | `findByNameAndAge` | `WHERE name=? AND age=?` | 多条件与连接 | | `Or` | `findByNameOrEmail` | `WHERE name=? OR email=?`| 多条件或连接 | | `Is` / `Equals`| `findByTitleIs` | `WHERE title = ?` | 等于(可省略) | | `Between` | `findByAgeBetween` | `WHERE age BETWEEN ? AND ?`| 范围查询 | | `LessThan` | `findByAgeLessThan` | `WHERE age < ?` | 小于 | | `LessThanEqual`| `findByAgeLessThanEqual` | `WHERE age <= ?` | 小于等于 | | `GreaterThan` | `findBySalaryGreaterThan` | `WHERE salary > ?` | 大于 | | `GreaterThanEqual`| `findBySalaryGreaterThanEqual`| `WHERE salary >= ?` | 大于等于 | --- #### 二、空值检查与集合操作 | 关键字 | 示例方法名 | 等效 SQL | |--------------|----------------------------|------------------------| | `IsNull` | `findByAddressIsNull` | `WHERE address IS NULL` | | `IsNotNull` | `findByEmailIsNotNull` | `WHERE email IS NOT NULL`| | `In` | `findByDepartmentIn` | `WHERE dept IN (?)` | | `NotIn` | `findByStatusNotIn` | `WHERE status NOT IN (?)`| --- #### 三、字符串匹配 | 关键字 | 示例方法名 | 等效 SQL | 说明 | |-----------------|-------------------------------|-----------------------|--------------------------| | `Like` | `findByNameLike` | `WHERE name LIKE ?` | 模糊匹配(需手动加`%`) | | `Containing` | `findByNameContaining` | `WHERE name LIKE %?%` | 包含指定字符串(自动加`%`)| | `StartingWith` | `findByNameStartingWith` | `WHERE name LIKE ?%` | 以指定字符串开头 | | `EndingWith` | `findByNameEndingWith` | `WHERE name LIKE %?` | 以指定字符串结尾 | | `IgnoreCase` | `findByNameIgnoreCase` | `WHERE LOWER(name)=LOWER(?)`| 忽略大小写 | --- #### 四、排序与分页 | 关键字 | 示例方法名 | 说明 | |-----------------|------------------------------------|----------------------------------------------------------------------| | `OrderBy` | `findBySexOrderByNameDesc`[^5] | 结果排序(`Asc`/`Desc`可省略,默认升序) | | `Pageable` | `findAll(Pageable pageable)`[^3] | 分页查询(需配合`PageRequest`参数) | | `Sort` | `findAll(Sort sort)`[^3] | 动态排序(非方法名关键字,通过参数传递) | --- #### 五、聚合与统计 | 关键字 | 示例方法名 | 说明 | |------------|-----------------------|--------------------------| | `countBy` | `countByStatus` | 统计满足条件的记录数 | | `deleteBy` | `deleteByExpiredDateBefore` | 删除满足条件的记录 | | `Distinct` | `findDistinctByName` | 去重查询 | --- #### 六、特殊场景关键字 | 关键字 | 示例方法名 | 说明 | |---------------|----------------------------|-------------------------------| | `True`/`False`| `findByActiveTrue()` | 布尔值查询(无需参数) | | `Before`/`After`| `findByCreateDateAfter` | 时间范围查询 | --- ### 使用示例 ```java // 组合查询:姓名包含"张"且年龄大于30,按姓名降序 List<User> users = userRepository.findByNameContainingAndAgeGreaterThanOrderByNameDesc("张", 30); // 分页查询:状态为ACTIVE,按创建时间倒序分页 Page<User> page = userRepository.findByStatus("ACTIVE", PageRequest.of(0, 10, Sort.by("createTime").descending())); ``` > **注意**: > - 属性名**首字母必须大写**(如`Name`而非`name`)[^1] > - 关键字与属性名**按顺序拼接**(如`findBy` + `Age` + `LessThan`) > - 参数顺序需与方法名中的**条件顺序一致** ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zonson9999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值