Трансформация запроса в 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;
Могли бы вы подсказать, каким образом можно наиболее правильно реализовать данную задачу? Буду рад любой наводке. Заранее спасибо.