Spring Data JPA recherche par propriété d'objet incorporé

101

Je veux écrire une signature de méthode d'interface de référentiel Spring Data JPA qui me permettra de trouver des entités avec une propriété d'un objet incorporé dans cette entité. Est-ce que quelqu'un sait si cela est possible et si oui comment?

Voici mon code:

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

}

Puis-je écrire une requête pour cela à l'aide de Spring Data?

CorayThan
la source
4
Ça ne findByBookIdRegion(Region region, Pageable pageable)fait pas l'affaire?
Oliver Drotbohm
2
Oui, ça le fait. Je n'ai trouvé aucune documentation à ce sujet. Est-ce caché ou implicite quelque part que je n'ai pas vu?
CorayJeu
J'ai transformé cela en une réponse et ajouté un lien vers la section pertinente des documents de référence.
Oliver Drotbohm

Réponses:

145

Ce nom de méthode devrait faire l'affaire:

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

Plus d'informations à ce sujet dans la section sur la dérivation de requêtes des documents de référence.

Oliver Drotbohm
la source
11
Que faire si j'ai une liste d'éléments intégrables? ou collection d'éléments?
user962206
Si nous voulons une requête findBy avec 3 preperty, quelle sera la syntaxe? est-ce comme findByPro1AndPro2AndPro3?
surendrapanday
Une telle requête aboutit-elle toujours à une jointure interne? Je fais One findByIdAndTwoId(Long oneId, Long twoId);et aboutit à une requête de la forme:select ...... from one one_ left outer join two two_ on one_.two_id = two_.id where one_id = ? and two_.id = ?
TroJaN
44

Le ci-dessus - findByBookIdRegion () n'a pas fonctionné pour moi. Ce qui suit fonctionne avec la dernière version de String Data JPA:

Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);
Bazinga
la source
3
Vos cas peuvent être liés à l'ambiguïté, comme indiqué sur docs.spring.io/spring-data/jpa/docs/current/reference/html/…
Marcello de Sales
9

Si vous utilisez BookId comme clé primaire combinée, n'oubliez pas de changer votre interface de:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> {

à:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, BookId> {

Et changez l'annotation @Embedded en @EmbeddedId, dans votre classe QueuedBook comme ceci:

public class QueuedBook implements Serializable {

@EmbeddedId
@NotNull
private BookId bookId;

...
Tim Kara
la source
1

Selon moi, Spring ne gère pas tous les cas avec facilité. Dans votre cas, ce qui suit devrait faire l'affaire

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

ou

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

Cependant, cela dépend également de la convention de dénomination des champs que vous avez dans votre @Embeddableclasse,

Par exemple, le champ suivant peut ne pas fonctionner dans l'un des styles mentionnés ci-dessus

private String cRcdDel;

J'ai essayé avec les deux cas (comme suit) et cela n'a pas fonctionné (il semble que Spring ne gère pas ce type de conventions de dénomination (c'est-à-dire à de nombreux Caps, en particulier au début - 2ème lettre (je ne sais pas si c'est le seul cas cependant)

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

ou

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

Quand j'ai renommé la colonne en

private String rcdDel;

mes solutions suivantes fonctionnent bien sans aucun problème:

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

OU

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