Трансформация запроса в JPQL

На текущий момент в проекте имеется БД для хранения товаров интернет-магазина, реализованная посредством ENV-паттерна (так как заранее неизвестно количество атрибутов/свойств товаров). Необходима реализация механизма фильтрации списка товаров, что выполняется следующим SQL-запросом (Postgres):

select *
from product p
         left join product_specification_value psv1 on p.id = psv1.product_id and psv1.specification_id = 1
         left join product_specification_value psv2 on p.id = psv2.product_id and psv2.specification_id = 2
where p.category_id = 2
    and (psv1.value = 'Сталь' or psv1.value = 'Железо')
    and (psv2.value = 'Фундаментные' or psv2.value = 'Комплектующие')

В данном случае производится жёсткое сопоставление конкретного свойства товара и переданных значений, так как одно и то же значение может относиться к разным атрибутам. Например, значение "20" может относиться, скажем, как к длине трубы, так и к её сечению.

Проблема в том, что количество атрибутов для каждого товара является разным и, таким образом, количество JOIN будет изменяться динамически, как и количество условий. Также в каждом из отдельных условий AND в скобках может быть множество условий OR (по количеству переданных значений для конкретного атрибута.

Скажите, пожалуйста, каким образом можно это можно реализовать с помощью JPQL? Все попытки каким-либо образом "размножить" JOIN приводят меня к следующего рода ошибке:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List by.trustor.api.repository.ProductRepository.findAllBySpecifications()!

Возможна ли трансформация подобного рода запроса в JPQL? Или же такое можно реализовать только путём генерации запроса "на лету" и выполнение его с помощью javax.persistence.Query? Либо же это будет можно реализовать с помощью CriteriaBuilder?

Также прилагаю устройства Entities, доступных на текущий момент:

@Entity
@Table(name = "product")
public class ProductEntity extends IdentifiableEntity {

    private String name;
    private String description;
    private Double price;
    private Double rating;
    private Long viewed;
    private LocalDateTime created;
    private LocalDateTime updated;

    @Enumerated(EnumType.STRING)
    private ProductStatus status;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "category_id", referencedColumnName = "id")
    private ProductCategoryEntity category;

    @OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
    private List<ProductSpecificationValueEntity> specifications;
@Entity
@Table(name = "product_specification_value")
public class ProductSpecificationValueEntity extends SerializableIdentifiableEntity {

    private String value;

    @ManyToOne
    @JoinColumn
    private ProductEntity product;

    @ManyToOne
    @JoinColumn
    private ProductSpecificationEntity specification;

Могли бы вы подсказать, каким образом можно наиболее правильно реализовать данную задачу? Буду рад любой наводке. Заранее спасибо.


Ответы (0 шт):