如何使用 JpaRepository 和嵌套的对象列表进行搜索?

Posted

技术标签:

【中文标题】如何使用 JpaRepository 和嵌套的对象列表进行搜索?【英文标题】:How to search with JpaRepository and nested list of objects? 【发布时间】:2018-06-08 08:55:39 【问题描述】:

说明

有一个PersonRepositoryPerson 实体, Person 类包含 List<Qualification>Qualification 类有 3 个简单字段。

我尝试在自定义方法上添加 @Query 注释并使用 JPQL 来获取结果,但 Qualification 类字段无法在 JPQL 中进行操作,因为它的存储库本身包含 List<Qualification> 而不仅仅是一个简单的字段Qualification.

如何通过这些 Qualification 的嵌套字段进行搜索?

查询

现在我需要查找资格的 experienceInMonths 大于 3 且小于 9 且资格的名称字段 = 'java' 的人员实体列表。

代码

Person.java

@Data
@Entity
public class Person 

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;

@NotEmpty
@Size(min = 2)
private String name;

@NotEmpty
@Size(min = 2)
private String surname;

@ElementCollection(targetClass = java.util.ArrayList.class, fetch = FetchType.EAGER)
private List<Qualification> qualifications = new ArrayList<>();


PersonRepository.java

@Repository
public interface PersonRepository extends JpaRepository<Person, String> 

Qualification.java

@Data
@AllArgsConstructor
public class Qualification implements Serializable 

    @Id @GeneratedValue
    private String id;
    private String name;
    private String experienceInMonths;

编辑:不重复this post,因为这里是嵌套对象的集合。不仅仅是单一参考。

【问题讨论】:

Spring Data JPA find by embedded object property的可能重复 如帖子编辑中所述,此问题与建议的答案不对应。正如您在粘贴的代码中看到的那样,List 的对象存在问题 - 而不仅仅是其中一个。 【参考方案1】:

首先,将experienceInMonthsString更改为int(否则无法将字符串与数字进行比较)。然后你可以尝试使用这个“香肠”:

List<Person> findByQualifications_experienceInMonthsGreaterThanAndQualifications_experienceInMonthsLessThanAndName(int experienceGreater, int experienceLess, String name);

或者你可以尝试使用这个相当不错的方法:

@Query("select p from Person p left join p.qualifications q where q.experienceInMonths > ?1 and q.experienceInMonths < ?2 and q.name = ?3")
List<Person> findByQualification(int experienceGreater, int experienceLess, String name);

【讨论】:

它在本地对您有用吗? JPQL 版本给了我org.hibernate.QueryException: cannot dereference scalar collection element: 和香肠之一:Caused by: java.lang.IllegalStateException: Illegal attempt to dereference path source [null] of basic type。即使将 Qualification#experienceInMonths 类型更改为 int @DevDio 尝试将@Entity 添加到Qualification 并将@ElementCollection 替换为@OneToMany(类似的变体对我有用...) 好的,终于让它工作了,但它需要在 Hibernate 中实现单独的Qualification 表。它将 FK 持有人(@Entity,具有@ManyToOne 的附加字段人)+QualificationRepository 是强制性的。还测试了提议的方法,带有 JPQL 的版本运行良好,但需要将“香肠”名称调整为:findByQualifications_experienceInMonthsGreaterThanAndQualifications_experienceInMonthsLessThanAndQualifications_Name。否则它会搜索人名。非常感谢@Cepr0 的帮助! @DevDio 'QualificationRepository 是强制性的' - 如果您使用 @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true),则没有必要。然后,您可以只使用一个 Person 存储库来存储这两个实体。【参考方案2】:

W 可以在方法名称中使用“_”(下划线)字符来定义 JPA 应该尝试拆分的位置。

在这种情况下,我们的方法名称将是

List<Person> findByQualification_name(String name);

【讨论】:

这在这里不起作用,你能检查一下吗? ***.com/questions/69753527/…

以上是关于如何使用 JpaRepository 和嵌套的对象列表进行搜索?的主要内容,如果未能解决你的问题,请参考以下文章

如何将对象从一个 JpaRepository 转换为另一个 JpaRepository

如何在 JpaRepository 中为多对一映射实体编写查询

如何使用 Spring Boot JpaRepository 保存多个表

我应该如何将 JpaRepository.findOne() 与 SpringBoot 一起使用?

如何制作没有类型的 JpaRepository,或者只制作查询的 jpa repo?

JpaRepository,如何查询 OneToMany 单向字段?