带有 QueryDslPredicateExecutor 并加入集合的 Spring-Data-JPA [英] Spring-Data-JPA with QueryDslPredicateExecutor and Joining into a collection

查看:42
本文介绍了带有 QueryDslPredicateExecutor 并加入集合的 Spring-Data-JPA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个这样的数据模型(伪代码):

Let's say I have a data model like this (pseudocode):

@Entity
Person {
    @OneToMany
    List<PersonAttribute> attributes;
}

@Entity
PersonAttribute {
    @ManyToOne
    AttributeName attributeName;

    String attributeValue;
}

@Entity
AttributeName {
    String name;
}

我定义了一个 Spring-Data-JPA 存储库,例如:

I have a Spring-Data-JPA repository defined such as:

public interface PersonRepository extends PagingAndSortingRepository<Person, Long>, QueryDslPredicateExecutor<Person>{}

我在 QueryDSL 文档中看到有一种机制可以将 Person 加入到 PersonAttribute,但看起来您需要访问 QueryDsl Query 对象,而存储库的客户端则没有.

I see in the QueryDSL documentation that there is a mechanism to Join from the Person to the PersonAttribute, but it looks like you need access to the QueryDsl Query object, which the client of the repository wouldn't have.

我想用我的 Predicate 做的是找到所有那些具有值为blue"的 AttributeValue(有一个连接)和一个名为eyecolor"的 AttributeName(还有另一个连接)的 Person.我不确定如何使用 any() 并强制我只得到那些带有 eye_color=blue 而不是带有 shoes_color=blue 的那些.

What I would like to do with my Predicate is to find all those Persons that have an AttributeValue (there's one join) with a value of "blue" and an AttributeName (there's another join) with a name of "eyecolor". I'm not sure how I would do that with an any() and enforce that I only get those with eye_color=blue and not those with shoe_color=blue.

我希望我能做这样的事情:

I was hoping I could do something like this:

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() 在那里,它只匹配具有蓝色"属性值的任何内容和具有眼睛颜色"属性的任何内容,而不管颜色如何.如何使这些条件适用于集合中的相同属性?

but with the any() in there it just matches anything with an attribute value of "blue" and anything with an "eye color" attribute regardless of color. How I can make those conditions apply to the same attribute within the set?

推荐答案

你不能在谓词中直接连接一列,但你可以像这样创建 any() 表达式

You can't directly join a column in a predicate but you can create an any() expressions like this

QPerson.person.attributes.any().attributeValue.eq("X")

这种方法的限制是连接表达式 QPerson.person.attributes.any() 只能在一个过滤器中使用.它的好处是这个表达式在内部被转换成一个不与分页冲突的子查询.

This approach has the restriction that the join expression QPerson.person.attributes.any() can be used in only one filter. It has though the benefit that this expression is internally converted into a subquery which doesn't conflict with paging.

对于多个限制,您需要像这样显式构建子查询表达式

For multiple restrictions you will need to construct a subquery expression explicitly like this

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 Data 使用 Querydsl 查询

In addition to QueryDslPredicateExecutor you can also use Querydsl queries via Spring Data like this

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/

这篇关于带有 QueryDslPredicateExecutor 并加入集合的 Spring-Data-JPA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆