12

I have a book class with a list of authors:

@Entity
@Table(name = "book")
public class Book extends Content {

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Author> authors;
...}

Now, this is my BookSpecifications class:

public static Specification<Book> authorIdIs(Long authorId) {
    return new Specification<Book>() {
        @Override
        public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
            return cb.isTrue(root.get("authors").get("id").in(authorId));
        }
    };
}

How can check the given authorId is in the list?

Error:

java.lang.IllegalStateException: Illegal attempt to dereference path source [null.authors] of basic type
    at org.hibernate.jpa.criteria.path.AbstractPathImpl.illegalDereference(AbstractPathImpl.java:98) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.jpa.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:191) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at com.tarameshgroup.derakht.service.specs.BookSpecifications$3.toPredicate(BookSpecifications.java:40) ~[classes/:na]
    at org.springframework.data.jpa.domain.Specifications$ComposedSpecification.toPredicate(Specifications.java:189) ~[spring-data-jpa-1.9.2.RELEASE.jar:na]
Harshal Patil
  • 6,659
  • 8
  • 41
  • 57
CVV
  • 451
  • 2
  • 7
  • 21
  • I'm not saying that I'll help, but can you please specify in detail how are you using it? This is a new construct for me, so I do not know, where is the `Specification` coming from and how to get it executed... It seems to me, the root is not initialized properly see `null` in `[null.authors]`, but it is not real NPE... – Betlista Jan 18 '16 at 11:08
  • Ok, I found some tutorial - https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/ ... – Betlista Jan 18 '16 at 11:10
  • 1
    @Betlista my problem is in searching in a list , – CVV Jan 18 '16 at 11:14
  • should be something like `builder.equal(root.get("authors").get("id").as(Long.class), authorId)` – Paizo Jan 18 '16 at 11:26

1 Answers1

17

For that you can use Join with predicate:

Refer below code,

public static Specification<Book> authorIdIs(Long authorId) {
    return new Specification<Book>() {
        @Override
        public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Join join = root.join("authors");                   
                return cb.equal(join.get("id"),authorId);
        }
    };
}
prem kumar
  • 5,641
  • 3
  • 24
  • 36
Harshal Patil
  • 6,659
  • 8
  • 41
  • 57