Spring Data JPA encuentra por propiedad de objeto incrustado


101

Quiero escribir una firma de método de interfaz de repositorio de Spring Data JPA que me permita encontrar entidades con una propiedad de un objeto incrustado en esa entidad. ¿Alguien sabe si esto es posible y, de ser así, cómo?

Aquí está mi 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);

}

¿Puedo escribir una consulta para esto usando Spring Data?


4
¿No funciona findByBookIdRegion(Region region, Pageable pageable)?
Oliver Drotbohm

2
Sí, eso es todo. No pude encontrar documentación para eso en ningún lado. ¿Está escondido o implícito en algún lugar que no vi?
CorayThan

Convirtió eso en una respuesta y agregó un enlace a la sección relevante de los documentos de referencia.
Oliver Drotbohm

Respuestas:


145

Este nombre de método debería funcionar:

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

Más información sobre eso en la sección sobre derivación de consultas de los documentos de referencia.


11
¿Qué pasa si tengo una lista de incrustables? o colección de elementos?
user962206

Si queremos findBy query con 3 propiedades, ¿cuál será la sintaxis? ¿es como findByPro1AndPro2AndPro3?
surendrapanday

¿Tal consulta siempre resulta en una combinación interna? Estoy haciendo One findByIdAndTwoId(Long oneId, Long twoId);y da como resultado una consulta de la forma:select ...... from one one_ left outer join two two_ on one_.two_id = two_.id where one_id = ? and two_.id = ?
TroJaN


9

Si está utilizando BookId como una clave primaria combinada, recuerde cambiar su interfaz de:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> {

a:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, BookId> {

Y cambie la anotación @Embedded a @EmbeddedId, en su clase QueuedBook así:

public class QueuedBook implements Serializable {

@EmbeddedId
@NotNull
private BookId bookId;

...

1

Según yo, Spring no maneja todos los casos con facilidad. En su caso, lo siguiente debería funcionar

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

o

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

Sin embargo, también depende de la convención de nomenclatura de los campos que tenga en su @Embeddableclase,

Por ejemplo, es posible que el siguiente campo no funcione en ninguno de los estilos mencionados anteriormente.

private String cRcdDel;

Intenté con ambos casos (como sigue) y no funcionó (parece que Spring no maneja este tipo de convenciones de nomenclatura (es decir, muchas mayúsculas, especialmente al principio) - 2da letra (no estoy seguro de si esto es aunque el único caso)

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

o

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

Cuando cambié el nombre de la columna a

private String rcdDel;

mis siguientes soluciones funcionan bien sin ningún problema:

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

O

Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.