I want to write a Spring Data JPA repository interface method signature that will let me find entities with a property of an embedded object in that entity. Does anyone know if this is possible, and if so how?
Here's my 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);
}
Can I write a query for this using Spring Data?
This method name should do the trick:
Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);
More info on that in the section about query derivation of the reference docs.
The above - findByBookIdRegion() did not work for me. The following works with the latest release of String Data JPA:
Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);
If you are using BookId as an combined primary key, then remember to change your interface from:
public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> {
to:
public interface QueuedBookRepo extends JpaRepository<QueuedBook, BookId> {
And change the annotation @Embedded to @EmbeddedId, in your QueuedBook class like this:
public class QueuedBook implements Serializable {
@EmbeddedId
@NotNull
private BookId bookId;
...
According to me, Spring doesn't handle all the cases with ease. In your case the following should do the trick
Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);
or
Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);
However, it also depends on the naming convention of fields that you have in your @Embeddable
class,
eg the following field might not work in any of the styles that mentioned above
private String cRcdDel;
I tried with both the cases (as follows) and it didn't work (it seems like Spring doesn't handle this type of naming conventions(ie to many Caps , especially in the beginning - 2nd letter (not sure about if this is the only case though)
Page<QueuedBook> findByBookIdCRcdDel(String cRcdDel, Pageable pageable);
or
Page<QueuedBook> findByBookIdCRcdDel(String cRcdDel, Pageable pageable);
When I renamed column to
private String rcdDel;
my following solutions work fine without any issue:
Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable);
OR
Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable);
There are different ways of doing this.
Below are code snippet showing how you can query data using embedded properties.
The repository extends the JpaSpecificationExecutor
interface.
public interface QuedBookRepository extends JpaRepository<QueuedBook, Long>, JpaSpecificationExecutor<QueuedBook>{
//Using derived query methods
Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);
//Using native queries
@Query("SELECT qb FROM QueuedBook qb "
+"WHERE qb.bookId.region = :region")
Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);
//Using specification interface
static Specification<QueuedBook> findByBookIdRegion(Region region){
return (root, query, criteriaBuilder) -> criteriaBuilder.equals(root.get("bookId").get("region"), region);
}
}
To use the repository methods, access them as follows.
//In your service methods
Region region = ....;
Pageable pageable = ....;
//Using derived query methods
Page<QueuedBook> booksPage = repository.findByBookId_Region(region, pageable);
//Using native queries
Page<QueuedBook> booksPage = repository.findByBookIdRegion(region, pageable);
//Using specification interface
Specification<QueuedBook> spec = QuedBookRepository.findByBookIdRegion(region);
Page<QueuedBook> booksPage = repository.findAll(spec, pageable);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.