如何使用 JpaRepository 和嵌套的对象列表进行搜索?
Posted
技术标签:
【中文标题】如何使用 JpaRepository 和嵌套的对象列表进行搜索?【英文标题】:How to search with JpaRepository and nested list of objects? 【发布时间】:2018-06-08 08:55:39 【问题描述】:说明
有一个PersonRepository
和Person
实体,
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】:
首先,将experienceInMonths
从String
更改为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 一起使用?