假设我有一个这样的数据模型(伪代码):
@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文档中看到有一个机制来从Person连接到PersonAttribute,但是看起来您需要访问存储库的客户端不会具有的QueryDsl Query对象.
我想要使用我的谓词是找到所有那些具有AttributeValue(有一个连接)的Person值(“blue”)和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()在那里它只是匹配任何与属性值“蓝色”和任何具有“眼睛颜色”属性的任何东西,无论颜色如何.如何使这些条件适用于集合中的相同属性?
解决方法
您不能直接连接谓词中的列,但您可以创建一个这样的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之外,您还可以通过Spring数据使用Querydsl查询
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/