Spring Data JPA 通过嵌入对象属性查找

Posted

技术标签:

【中文标题】Spring Data JPA 通过嵌入对象属性查找【英文标题】:Spring Data JPA find by embedded object property 【发布时间】:2014-08-17 22:46:44 【问题描述】:

我想编写一个 Spring Data JPA 存储库接口方法签名,它可以让我在该实体中找到具有嵌入对象属性的实体。有谁知道这是否可行,如果可以,怎么办?

这是我的代码:

@Entity
@Table(name = "BOOK_UPDATE_QUEUE", indexes =  uniqueConstraints = @UniqueConstraint(columnNames = 
        "bookId", "region" , name = "UK01_BOOK_UPDATE_QUEUE"))
public class QueuedBook implements Serializable 

    @Embedded
    @NotNull
    private BookId bookId;

    ...



@Embeddable
public class BookId implements Serializable 

    @NotNull
    @Size(min=1, max=40)
    private String bookId;

    @NotNull
    @Enumerated(EnumType.STRING)
    private Region region;

    ...



public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> 

    //I'd like to write a method like this, but can't figure out how to search by region,
    //when region is actually a part of the embedded BookId
    Page<QueuedBook> findByRegion(Region region, Pageable pageable);


我可以使用 Spring Data 为此编写查询吗?

【问题讨论】:

findByBookIdRegion(Region region, Pageable pageable) 不成功吗? 是的,就是这样。我在任何地方都找不到相关文档。它是隐藏在我没看到的地方还是隐含在某处? 将其转换为答案并添加了指向参考文档相关部分的链接。 【参考方案1】:

在我看来,Spring 并不能轻松处理所有情况。在你的情况下 以下应该可以解决问题

Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);  

Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);

但是,这也取决于您在 @Embeddable 类中的字段命名约定,

例如以下字段可能不适用于上述任何样式

private String cRcdDel;

我尝试了这两种情况(如下)但它没有工作(似乎 Spring 不处理这种类型的命名约定(即许多 Caps ,尤其是在开头 - 第二个字母(不确定如果这是唯一的情况)

Page<QueuedBook> findByBookIdCRcdDel(String cRcdDel, Pageable pageable); 

Page<QueuedBook> findByBookIdCRcdDel(String cRcdDel, Pageable pageable);

当我将列重命名为

private String rcdDel;

我的以下解决方案可以正常工作,没有任何问题:

Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable); 

Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable);

【讨论】:

【参考方案2】:

如果您使用 BookId 作为组合主键,请记住将您的界面更改为:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> 

到:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, BookId> 

并在你的 QueuedBook 类中将注释 @Embedded 更改为 @EmbeddedId,如下所示:

public class QueuedBook implements Serializable 

@EmbeddedId
@NotNull
private BookId bookId;

...

【讨论】:

【参考方案3】:

以上 - findByBookIdRegion() 对我不起作用。以下适用于最新版本的 String Data JPA:

Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);

【讨论】:

您的案例可能与 docs.spring.io/spring-data/jpa/docs/current/reference/html/… 讨论的模棱两可有关【参考方案4】:

这个方法名应该可以解决问题:

Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);

更多信息请参见参考文档的 query derivation 部分。

【讨论】:

如果我有一个可嵌入列表怎么办?还是元素集合? 如果我们想要 findBy 查询 3 preperty 那么语法是什么?和 findByPro1AndPro2AndPro3 一样吗? 这样的查询总是会导致内连接吗?我正在做One findByIdAndTwoId(Long oneId, Long twoId); 并导致以下形式的查询:select ...... from one one_ left outer join two two_ on one_.two_id = two_.id where one_id = ? and two_.id = ? @surendrapanday:是的,findByCol1AndCol2 在您有多个列时有效

以上是关于Spring Data JPA 通过嵌入对象属性查找的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA:查询如何返回非实体对象或对象列表?

Spring-data-jpa介绍

如何禁用嵌入式数据库 Spring-boot spring-data-jpa

学习Spring-Data-Jpa(二十一)---DataSource与JPA属性配置

使用Spring-data-jpa(三十)

选择特定列的 Spring Data JPA 规范