Перепишите запрос в JPA - PullRequest
0 голосов
/ 06 ноября 2018

Я хочу переписать этот запрос SQL в JPA.

String hql = "SELECT date(created_at) AS cdate, sum(amount) AS amount, count(id) AS nooftransaction "
                + "FROM payment_transactions WHERE date(created_at)>=date(now()- interval 10 DAY) "
                + "AND date(created_at)<date(now()) GROUP BY date(created_at)";

        TypedQuery<Merchants> query = entityManager.createQuery(hql, Merchants.class);
        List<Merchants> merchants = query.getResultList();

Есть ли способ переписать запросы в JPA, или я должен использовать его как есть?

Ответы [ 6 ]

0 голосов
/ 20 ноября 2018

В вашем классе сущностей, представляющем таблицу 'payment_transactions', добавьте следующее:

@SqlResultSetMapping(
    name = "PaymentTransaction.summaryMapping",
    classes = {
        @ConstructorResult(targetClass = PaymentTransactionSummary.class,
                columns = {
                    @ColumnResult(name = "cdate")
                    , @ColumnResult(name = "amount")
                    , @ColumnResult(name = "nooftransaction")
                })
    }         
)

Создайте новый класс pojo с именем PaymentTransactionSummary (должен совпадать с именем, использованным выше, или любым другим именем, которое вы выбираете, с полями членов cdate, amount и nooftransaction. Включите конструктор, который включает эти три поля в указанном выше порядке.

Тогда в своем классе дао напишите это:

Query q = entityManager.createNativeQuery("your query string from above"
    , "PaymentTransaction.summaryMapping");
List<PaymentTransactionSummary> results = q.getResultList();
0 голосов
/ 16 ноября 2018

Вы можете использовать ниже код

CriteriaBuilder qb = entityManager.getCriteriaBuilder();
CriteriaQuery cq = qb.createQuery();
Root paymentInstructionsRoot = cq.from(PaymentInstructions.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(qb.greaterThanOrEqualTo(path, fromDateRange));
predicates.add(qb.lessThanOrEqualTo(path, toDateRange));

Selection cdate = paymentInstructionsRoot.get(PaymentInstructions_.createdAt).alias("cdate");
Selection amount = qb.sum(paymentInstructionsRoot.get(PaymentInstructions_.amount))).alias("amount");
Selection nooftransaction = qb.count(paymentInstructionsRoot.get(PaymentInstructions_.id))).alias("nooftransaction");

Selection[] selectionExpression = {cdate, amount, nooftransaction};
Expression[] groupByExpression = {paymentInstructionsRoot.get(PaymentInstructions_.createdAt)};
cq.multiselect(selectionExpression).where(predicates.toArray(new Predicate[]{})).groupBy(groupByExpression).where(predicates.toArray(new Predicate[]{}));

List<PaymentInstructions> paymentInstructions = entityManager.createQuery(cq).getResultList();
0 голосов
/ 16 ноября 2018

Вы не предоставляете никаких сведений о классах и сущностях, но это может быть что-то вроде:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = builder.createTupleQuery();
From<PaymentTransaction> tx = query.from(PaymentTransaction.class);
Expression<Long> sumAmount = builder.sum(tx.get("amount"));
Expression<Long> count = builder.count(tx.get("id"));
Expression<Date> createdAt = tx.get("created_at");
query.multiselect(createdAt, sumAmount, count);
query.where(builder.greaterThanOrEqualTo(createdAt, builder.function("DATEADD", "DAY", new Date(), builder.literal(-10))),
    builder.lessThan(createdAt, new Date()));
query.groupBy(createdAt);

entityManager.createQuery(query).getResultList().stream()
    .map(t -> new Merchants(t.get(0, Date.class), t.get(1, Long.class), t.get(2, Long.class)))
    .collect(Collectors.toList());
0 голосов
/ 16 ноября 2018

В подобных ситуациях чаще всего лучше всего написать простое представление SQL:

CREATE OR REPLACE VIEW payment_transactions_stats AS
SELECT date(created_at) AS cdate, sum(amount) AS amount, count(id) AS nooftransaction
FROM payment_transactions
WHERE date(created_at)>=date(now()- interval 10 DAY)
AND date(created_at)<date(now()) GROUP BY date(created_at);

И сопоставьте его с @Immutable сущностью. Этот подход хорошо работает, когда:

  • у вас есть данные только для чтения
  • представлению не нужны параметры (в этом случае также есть решения, которые варьируются от hacky до nice )
0 голосов
/ 16 ноября 2018

Поскольку вопрос помечен с помощью spring-data-jpa, вы можете попробовать использовать Spring CRUDRepository в верхней части таблицы. В CRUDRepository напишите пользовательский метод с аннотацией @ Query .

Мне сложно сформулировать весь запрос, потому что я не знаю членов вашего класса Merchants.

В качестве альтернативы вы можете установить nativeQuery = true для аннотации @Query и использовать фактический запрос БД для решения вашей проблемы.

0 голосов
/ 15 ноября 2018

Лучше не использовать JPA для сложных запросов, подобных этому. JPA обычно используются для простых запросов.

...