Java – filter collections by multiple attributes of their elements – querydsl

I am studying the dynamic filter component based on query DSL and using spring data for query execution Therefore, I create a predicate instance from the received data AD and pass it to querydslpredicateexecutor For dynamic access to entity properties, I use a generic pathbuilder that types entity classes

Consider the following (Simplified) codes:

class Offer {
    List<LanguageToName> names;
}
class LanguageToName {
    String name;
    String language;
}

When I try to query offer entities, I have the attribute 'ABC' in its collection name element. I just need to create a predicate, as shown below:

pathBuilder.getCollection("names",LanguageToName.class).any().getString("name")
    .like("%" + fieldData.getFieldValue() + "%");

However, I can't come up with a solution to use pathbuilder to filter collections by containing multiple properties of objects When I use And () when attaching the above code and accessing the collection again through the pathbuilder variable, I will naturally get the result equivalent to attaching the SQL query using and exists... Which is not the desired result I also try to use getcollection() Contains(), but I can't create expression < languagetoname >, which will describe this situation

Is there any way to create a predicate that can filter entities through multiple attributes of elements in the collection, which is a field of query entities?

Solution

I encountered the same problem in the project

Suppose your two classes are mapped to entities:

@Entity
@Table(name = "Offer")
public class Offer {

    @Id
    String id;

    @OneToMany(fetch = FetchType.LAZY,mappedBy = "offer")
    List<LanguageToName> names;
}

@Entity
@Table(schema = "dcsdba",name = "Language_To_Name")
public class LanguageToName {

    @Id
    String id;

    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumn(name="Offer_id")
    private Offer offer;

    String name;
    String language;
}

Use any() for a simple query:

BooleanExpression namesFilter = QOffer.offer.names.any().name.eq("Esperanto");

Map to

select
    offer0_.id as id1_7_ 
from
    offer offer0_ 
where
    exists (
        select
            1 
        from
            dcsdba.language_to_name names1_ 
        where
            offer0_.id=names1_.offer_id 
            and names1_.name=?
    )

Subquery:

BooleanExpression namesFilter = JPAExpressions.selectOne()
            .from(languageToName)
            .where(languageToName.offer.eq(QOffer.offer)
                    .and(languageToName.name.eq("Esperanto")))
            .exists();

Map to:

select
    offer0_.id as id1_7_ 
from
    offer offer0_ 
where
    exists (
        select
            1 
        from
            dcsdba.language_to_name languageto1_ 
        where
            languageto1_.offer_id=offer0_.id 
            and languageto1_.name=?
    )

It exactly matches the previous SQL You can add other conditions, such as:

BooleanExpression namesFilter = JPAExpressions.selectOne()
            .from(languageToName)
            .where(languageToName.offer.eq(QOffer.offer)
                    .and(languageToName.name.eq("Esperanto"))
                    .and(languageToName.language.like("E%")))
            .exists();
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>