Spring Data JPA localizar por propriedade de objeto incorporado

101

Eu quero escrever uma assinatura de método de interface de repositório Spring Data JPA que me permitirá encontrar entidades com uma propriedade de um objeto incorporado nessa entidade. Alguém sabe se isso é possível e se sim como?

Este é o meu código:

@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);

}

Posso escrever uma consulta para isso usando Spring Data?

CorayThan
fonte
4
Não findByBookIdRegion(Region region, Pageable pageable)faz o truque?
Oliver Drotbohm
2
Sim, é isso. Não consegui encontrar documentação para isso em lugar nenhum. Está escondido ou implícito em algum lugar que eu não vi?
CorayThan
Transformei isso em uma resposta e adicionei um link para a seção relevante dos documentos de referência.
Oliver Drotbohm

Respostas:

145

Este nome de método deve fazer o truque:

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

Mais informações sobre isso na seção sobre derivação de consulta dos documentos de referência.

Oliver Drotbohm
fonte
11
E se eu tiver uma lista de incorporáveis? ou coleção de elementos?
user962206
Se quisermos uma consulta findBy com 3 preperty, qual será a sintaxe? é como findByPro1AndPro2AndPro3?
surendrapanday
Essa consulta sempre resulta em uma junção interna? Estou fazendo One findByIdAndTwoId(Long oneId, Long twoId);e resulta em uma consulta do formulário:select ...... from one one_ left outer join two two_ on one_.two_id = two_.id where one_id = ? and two_.id = ?
TroJaN
44

O acima - findByBookIdRegion () não funcionou para mim. O seguinte funciona com a versão mais recente do String Data JPA:

Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);
Bazinga
fonte
3
Seus casos podem estar relacionados à ambigüidade, conforme discutido em docs.spring.io/spring-data/jpa/docs/current/reference/html/…
Marcello de Sales
9

Se você estiver usando BookId como uma chave primária combinada, lembre-se de alterar sua interface de:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> {

para:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, BookId> {

E altere a anotação @Embedded para @EmbeddedId, em sua classe QueuedBook assim:

public class QueuedBook implements Serializable {

@EmbeddedId
@NotNull
private BookId bookId;

...
Tim Kara
fonte
1

Na minha opinião, o Spring não lida com todos os casos com facilidade. No seu caso, o seguinte deve resolver

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

ou

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

No entanto, também depende da convenção de nomenclatura dos campos que você tem em seu @Embeddable classe,

por exemplo, o campo a seguir pode não funcionar em nenhum dos estilos mencionados acima

private String cRcdDel;

Eu tentei com ambos os casos (como segue) e não funcionou (parece que o Spring não lida com este tipo de convenções de nomenclatura (ou seja, para muitos Caps, especialmente no início - 2ª letra (não tenho certeza se este é embora o único caso)

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

ou

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

Quando eu renomei a coluna para

private String rcdDel;

minhas seguintes soluções funcionam bem sem qualquer problema:

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

OU

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