API критериев JPA поиск по вложенному списку объектов по полю

#hibernate #jpa #criteria-api

#переход в спящий режим #jpa #критерии-api

Вопрос:

У меня есть Certificate класс, который содержит список Tag классов (многие ко многим), и я должен найти Certificates , которые содержат определенные Tag (по имени тега) Я использую API критериев JPA, но не могу этого сделать..

 @Entity
@Table(name = "gift_certificate")
public class Certificate {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String description;
    private BigDecimal price;
    private Integer duration;
    @Column(name = "create_date")
    private LocalDateTime createDate;
    @Column(name = "last_update_date")
    private LocalDateTime lastUpdateDate;
    @ManyToMany
    @JoinTable(name = "gift_certificate_tag",
            joinColumns = @JoinColumn(name = "tag_id"),
            inverseJoinColumns = @JoinColumn(name = "gift_certificate_id")
    )
    private List<Tag> tags;
    
getters and setters and other code...
 

…..

 @Entity
@Table(name = "tag")
public class Tag {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

getters and setters and other code...
 

Я пытался сделать это так, но я получаю исключение IllegalStateException: Illegal attempt to dereference path source [null.tags] of basic type

 CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Certificate> query = cb.createQuery(Certificate.class);
Root<Certificate> certificates = query.from(Certificate.class);
certificates.fetch("tags", JoinType.LEFT);
query.select(certificates).distinct(true);

query.where(cb.like(certificates.get("tags").get("name"), params.getTag()));

return entityManager.createQuery(query).getResultList();
 

Ответ №1:

Я сделал это!

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
   CriteriaQuery<Certificate> criteriaQuery = cb.createQuery(Certificate.class);
   Root<Certificate> certificates = criteriaQuery.from(Certificate.class);

   Join<Certificate, Tag> tags = certificates.join("tags", JoinType.LEFT);
   criteriaQuery = criteriaQuery.distinct(true).where(cb.like(tags.get("name"), params.getTag()));

   return entityManager.createQuery(criteriaQuery).getResultList();