Spring Boot: как создать динамический запрос c, включающий 'join' и 'group by', используя предикат - PullRequest
0 голосов
/ 01 мая 2020

Тело моего почтового запроса будет выглядеть так:

{
    "queryCondition":[
            {
                "filter":"status",
                "filterlist":["Closed","New","Resolved"...]
            },
            {
                "filter":"assigned_team",
                "filterlist":["A","B","C"...]
            },
            {
                "filter":"assigned_to",
                "filterlist":["ram","govind","ajith"...]
            },
            {
                "filter":"duration",
                "filterlist":["2020-02-01","2020-05-01"....]
            }
            ....
            ....
        ],
    "durationField":"created_date"
}

Я получаю динамически столбцы (фильтр) и значения (список фильтров), с помощью которых мне нужно создать этот запрос.

SELECT * FROM tickets 
WHERE ticket_id IN (SELECT ticket_id FROM Tickets WHERE created_date >= '2020-02-01') AND created_date '2020-05-01'
AND status IN ('Closed','Resolved','New')
AND assigned_team IN ('A' , 'B', 'C')
AND assigned_to IN ('ram','govind','ajith');

Я построил этот запрос динамически, используя Predicate, и он работает нормально.

@Override
public List<Tickets> conditionedQuery(QueryCondition queryCondition) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Tickets> query = cb.createQuery(Tickets.class);
    Root<Tickets> ticket = query.from(Tickets.class);
    List<Predicate> predicatessub = new ArrayList<>();
    for(FilterConditions fc:queryCondition.getQueryCondition()) {
        if(fc.getFilter().equals("duration")) {
            Predicate ps = cb.greaterThanOrEqualTo(ticket.get(queryCondition.getDurationField()), fc.getFilterlist()[0]);
            Predicate pe = cb.lessThan(ticket.get(queryCondition.getDurationField()), fc.getFilterlist()[1]);
            predicatessub.add(cb.and(ps,pe));
        }else 
        {
            List<Predicate> predicates = new ArrayList<>();
            for(int i=0; i<fc.getFilterlist().length; i++) {
                Predicate p = cb.equal(ticket.get(fc.getFilter()),fc.getFilterlist()[i]);
                predicates.add(p);
            }
            predicatessub.add(cb.or(predicates.toArray(new Predicate[predicates.size()])));
        }
    }
    query.select(ticket)
    .where(cb.and(predicatessub.toArray(new Predicate[predicatessub.size()])));
    return entityManager.createQuery(query)
    .getResultList();
}

QueryCondition.class

public class QueryCondition {
    private List<FilterConditions> filterCondition;
    private String durationField;
}

FilterConditions.class

public class FilterConditions {
    private String filter;
    private String[] filterlist;
}

Теперь я хотел бы построить более сложный запрос, включающий объединения и группирование по. Ниже приведен пример запроса, подобный тому, который я хотел бы построить с использованием предиката.

SELECT 
YEAR(pt.created_date),
MONTH(pt.created_date),
pt.assigned_team,
COUNT(tk.ticket_id)
FROM
(SELECT 
    *
FROM
    tickets
WHERE
    ticket_id IN (SELECT 
            ticket_id
        FROM
            Tickets
        WHERE
            resolved_date >= '2020-02-01')
        AND resolved_date < '2020-05-01'
        and assigned_team IN ('A' , 'B', 'C')) pt
    LEFT JOIN
(SELECT 
    *
FROM
    tickets
WHERE
    status IN ('Closed','Resolved','New')
        AND assigned_to IN ('ram','govind','ajith')) tk ON tk.ticket_id = pt.ticket_id
GROUP BY YEAR(pt.created_date) , MONTH(pt.created_date), pt.assigned_team order by 
pt.assigned_team,YEAR(pt.created_date),MONTH(pt.created_date) asc;

Пожалуйста, посоветуйте, как этого можно достичь с помощью Predicate или есть какой-либо более простой способ, чем Predicate.

...