CriteriaBuilder.construct - проекция DTO - PullRequest
0 голосов
/ 03 июля 2019

Я делаю объект отчета DTO, который содержит еще два DTO, как показано:

@Getter
@Setter
@ToString
@AllArgsConstructor
@Accessors(chain = true)
public class ReportDTO implements Serializable {

    private Transaction transaction;

    private Payment payment;

    @Getter
    @Setter
    @ToString
    @AllArgsConstructor
    @Accessors(chain = true)
    public static class Transaction implements Serializable {

        private Long id;

        private TransactionStatus status;

        private String currency;

        private BigDecimal total;
    }

    @Getter
    @Setter
    @ToString
    @AllArgsConstructor
    @Accessors(chain = true)
    public static class Payment implements Serializable {

        private Long tid;

        private String currency;

        private BigDecimal total;
    }
}

Я пытаюсь заполнить его с помощью API CriteriaQuery, вот так:

public <T extends Transaction> List<ReportDTO> generateReport(final Specification<T> specification, Class<T> classx) {

        CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
        CriteriaQuery<ReportDTO> criteriaQuery = criteriaBuilder.createQuery(ReportDTO.class);

        Root<T> root = criteriaQuery.from(classx);
        criteriaQuery.select(criteriaBuilder.construct(
                ReportDTO.class,
                criteriaBuilder.construct(
                        ReportDTO.Transaction.class,
                        root.get("id"),
                        root.get("status"),
                        root.get("currency"),
                        root.get("total")
                ),
                criteriaBuilder.construct(
                        ReportDTO.Payment.class,
                        root.get("payment").get("tid"),
                        root.get("currency"),
                        root.get("payment").get("amount")
                )
        ));

        criteriaQuery.where(specification.toPredicate(root, criteriaQuery, criteriaBuilder));
        criteriaQuery.orderBy(criteriaBuilder.desc(root.get("date")));
        TypedQuery<ReportDTO> typedQuery = this.entityManager.createQuery(criteriaQuery);

        return typedQuery.getResultList();
    }

Но ... Судя по всему, я не могу использовать критерий Builder.construct внутри другого критерия Builder.construct ...

Вот вывод частичного исключения:

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: new near line 1, column XX [select new com.demo.ReportDTO(new com.demo.ReportDTO$Transaction(generatedAlias0.id, generatedAlias0.status, generatedAlias0.currency, generatedAlias0.total)) from com.demo.Transactions as generatedAlias0 where generatedAlias0.date between :param0 and :param1 order by generatedAlias0.date desc]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:288) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:187) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:531) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.criteria.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:316) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.criteria.compile.CriteriaCompiler.compile(CriteriaCompiler.java:130) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:699) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at com.sun.proxy.$Proxy141.createQuery(Unknown Source) ~[na:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]

Интересно, есть ли способ заполнить, используя Criteria API.

Я уже успешно поместил все внутренние атрибуты в ReportDTO, но этот способ выглядит более чистым для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...