Spring Data 根据嵌套对象的属性检索数据

1、概览

在 Spring Data 中,使用基于方法名称的派生查询来查询实体是很常见的。在处理实体之间的关系(如嵌套对象)时,Spring Data 提供了各种机制来检索这些嵌套对象中的数据。

本文将带你了解如何使用查询派生和 JPQL(Java 持久性查询语言)通过嵌套对象的属性进行查询。

2、场景概述

考虑一个有两个实体的简单场景:CustomerOrder。每个 Order 都通过 ManyToOne(多对一)关系关联到一个 Customer

我们要查找属于某个 Customer 的所有 Order,该 Customer 有特定的 email。在这种情况下,emailCustomer 实体的属性,而我们的主要查询将在 Order 实体上执行。

实体示例如下:

@Entity
@Table(name = "customers")
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String email;

   // Getter / Setter 省略
}

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Date orderDate;

    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;

   // Getter / Setter 省略
}

3、使用派生查询

Spring Data JPA 允许开发者从 Repository 接口中的方法签名派生查询,从而简化了查询创建:

3.1、常规使用案例

在一般情况下,如果我们想通过相关 Customeremail 查找 Order 实体,我们可以简单地这样做:

public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByCustomerEmail(String email);
}

生成的 SQL 如下:

select
    o.id,
    o.customer_id,
    o.order_date
from
    orders o
left outer join
    customers c
        on o.customer_id = c.id
where
    c.email = ?

3.2、关键字冲突的情况

现在,假设除了嵌套的 Customer 对象外,我们还在 Order 类中设置了一个名为 customerEmail 的字段。在这种情况下,Spring Data JPA 不会像我们期望的那样只在 customers 表中生成查询:

select
    o.id,
    o.customer_id,
    o.customer_email,
    o.order_date
from
    orders o
where
    o.customer_email = ?

在这种情况下,我们可以使用 下划线字符 来定义 JPA 应尝试分割关键字的位置:

List<Order> findByCustomer_Email(String email);

如上,下划线有助于 Spring Data JPA 正确解析查询方法。

4、使用 JPQL 查询

如果我们想对查询逻辑进行更多控制或执行更复杂的操作,JPQL 是一个不错的选择。要使用 JPQL 按 Customeremail 查询 Order,我们可以这样写

@Query("SELECT o FROM Order o WHERE o.customer.email = ?1")
List<Order> findByCustomerEmailAndJPQL(String email);

这样,我们就可以灵活地编写更有针对性的查询,而不必依赖方法名称约定。

5、总结

本文介绍了如何通过 Spring Data 中嵌套对象的属性来查询数据,主要介绍了派生查询和自定义 JPQL 查询的场景下的用法。


Ref:https://www.baeldung.com/spring-data-find-by-property-nested-object