Spring-Data-JPA с QueryDslPredicateExecutor и присоединением к коллекции
предположим, у меня есть такая модель данных (псевдокод):
@Entity
Person {
@OneToMany
List<PersonAttribute> attributes;
}
@Entity
PersonAttribute {
@ManyToOne
AttributeName attributeName;
String attributeValue;
}
@Entity
AttributeName {
String name;
}
у меня есть репозиторий Spring-Data-JPA, определенный как:
public interface PersonRepository extends PagingAndSortingRepository<Person, Long>, QueryDslPredicateExecutor<Person>{}
Я вижу в документации QueryDSL, что есть механизм для присоединения от человека к PersonAttribute, но похоже, что вам нужен доступ к объекту запроса QueryDsl, которого у клиента репозитория не было бы.
что я хотел бы сделать с моим сказуемым, чтобы найти всех тех людей, которые имеют AttributeValue (есть одно соединение) со значением "синий" и AttributeName (есть другое соединение) с именем "eyecolor". Я не уверен, как бы я сделал это с any()
и убедитесь, что я получаю только те, у кого eye_color=blue, а не те, у кого shoe_color=blue.
Я надеялся, что смогу сделать что-то вроде этого:
QPerson person = QPerson.person;
QPersonAttribute attribute = person.attributes.any();
Predicate predicate = person.name.toLowerCase().startsWith("jo")
.and(attribute.attributeName().name.toLowerCase().eq("eye color")
.and(attribute.attributeValue.toLowerCase().eq("blue")));
но с any()
там он просто соответствует чему-либо со значением атрибута "синий" и что-либо с атрибутом "цвет глаз" независимо от цвета. как я могу применить эти условия к одному и тому же атрибуту в наборе?
1 ответов
вы не можете напрямую присоединиться к столбцу в предикате, но вы можете создать выражения any (), подобные этому
QPerson.person.attributes.any().attributeValue.eq("X")
этот подход имеет ограничение, что выражение соединения QPerson.person.attributes.any()
может использоваться только в одном фильтре. Это имеет, хотя преимущество, что это выражение внутренне преобразуется в подзапрос, который не конфликтует с подкачкой.
для нескольких ограничений вам нужно будет построить выражение подзапроса явно, как это
QPersonAttribute attribute = QPersonAttribute.personAttribute;
new JPASubQuery().from(attribute)
.where(attribute.in(person.attributes),
attribute.attributeName().name.toLowerCase().eq("eye color"),
attribute.attributeValue.toLowerCase().eq("blue"))
.exists()
кроме QueryDslPredicateExecutor
вы также можете использовать запросы Querydsl через данные Spring, как это
public class CustomerRepositoryImpl
extends QueryDslRepositorySupport
implements CustomerRepositoryCustom {
public Iterable<Customer> findAllLongtermCustomersWithBirthday() {
QCustomer customer = QCustomer.customer;
return from(customer)
.where(hasBirthday().and(isLongTermCustomer()))
.list(customer);
}
}
пример взят отсюда https://blog.42.nl/articles/spring-data-jpa-with-querydsl-repositories-made-easy/