Представьте себе следующую иерархию сущностей:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", columnDefinition = "varchar(60)")
abstract class Resource {
}
@Entity
@DiscriminatorValue("resource1")
class Resource1 extends Resource {
@Embedded
private Property property1;
}
@Entity
@DiscriminatorValue("resource2")
class Resource2 extends Resource {
@Embedded
private Property property2;
}
@Entity
@DiscriminatorValue("resource3")
class Resource3 extends Resource {
@Embedded
private Property property3;
}
@Entity
@DiscriminatorValue("resource4")
class Resource4 extends Resource {
@Embedded
private Property property4;
}
@Entity
class EntityUsingResource {
@OneToMany(...)
@JoinColumn(...)
private List<Resource> resources;
}
Я пытаюсь создать пользовательский интерфейс для поиска EntityUsingResource
s и могу фильтровать элементы, которые имеют ресурсы с определенным свойством.
Таким образом, в поле поиска в графическом интерфейсе можно ввести значение, скажем, property4
, и оно отфильтровывает все EntityUsingResource
с ресурсом типа Resource4
, свойство которого4 которого равно введенному вами.
До сих пор мне удавалось сделать это, используя этот критерий API с использованием спецификаций пружин:
public static Specification<EntityUsingResource>
withResource4HavingProperty4Like(String property4) {
Join<EntityUsingResource, Resource> join =
root.join(EntityUsingResource_.resources, JoinType.INNER);
Join<EntityUsingResource, Resource4> treatedJoin =
cb.treat(join, Resource4.class);
return cb.like(
treatedJoin.get(Resource4_.property4).get(Property_.value),
"%" + property4 + "%");
}
public static Specification<EntityUsingResource>
withResource2HavingProperty2Like(String property2) {
Join<EntityUsingResource, Resource> join =
root.join(EntityUsingResource_.resources, JoinType.INNER);
Join<EntityUsingResource, Resource2> treatedJoin =
cb.treat(join, Resource2.class);
return cb.like(
treatedJoin.get(Resource2_.property2).get(Property_.value),
"%" + property2 + "%");
}
Я использую эти спецификации с утилитой класса Спецификации пружин следующим образом: где (withResource2HavingProperty2Like (property2)) .and(withResource4HavingProperty4Like (property4));
которые я затем передаю JpaRepository
и более или менее возвращаю результат в графический интерфейс.
Это создает следующий SQL при поиске property1:
select
entity_using_resource0.id as entityId
from
entity_using_resource entity_using_resource0
inner join resource resourceas1_ on
entity_using_resource0.id=resourceas1_.entity_using_resource_id
inner join resource resourceas2_ on
entity_using_resource0.id=resourceas2_.entity_using_resource_id
inner join resource resourceas3_ on
entity_using_resource0.id=resourceas3_.entity_using_resource_id
inner join resource resourceas4_ on
entity_using_resource0.id=resourceas4_.entity_using_resource_id
where (resourceas4_.property1 like 'property1')
and (resourceas2_.property1 like '%property1%') limit ...;
Проблема в том, что этот запрос выдает много дубликатов. Я попытался использовать различные, которые могли бы решить проблему, но возникает другая. В сущности EntityUsingResource
у меня есть столбец, который имеет тип json, поэтому использование различных не будет работать, поскольку база данных не может сравнивать значения json.
Как написать запрос, который также фильтрует длятип Resource
используя критерии api?
Заранее спасибо: -)