QueryDSL, недопустимый тип аргумента при проецировании перечисления из JPASQLQuery в DTO

Мы должны использовать JPASQLQueries для сложных запросов с объединениями в произвольных столбцах и подзапросах. Один такой запрос возвращает строку из БД и должен проецировать ее на перечисление в DTO. Это сопоставление завершается с "недопустимым типом аргумента" при попытке вызвать установщик в DTO для этого конкретного значения.
Сопоставление с сущностью с той же структурой, что и DTO.

Это запрос, который я использую:

    final QOrderHeader orderHeader = QOrderHeader.orderHeader;
    QOrderHeader orderGroup = new QOrderHeader("orderGroup");
    QOrderPosition orderPosition = QOrderPosition.orderPosition;

    SQLTemplates templates = new OracleTemplates();
    JPASQLQuery orderQuery = new JPASQLQuery(em, templates);
    Predicate preds = OrderHeaderPredicate.matchesSearchCriteria(searchCriteria);

    // select from entity metadata, bind onto DTO, use entity metadata
    List<OrderHeaderDTO> orderHeaderWithInfos = orderQuery //
            .from(orderHeader) //
            .list(Projections.bean(OrderHeaderDTO.class, //
                    .. some values left out
                    orderHeader.orderGroup, //
                    orderHeader.orderTypeCode, //
                    orderHeader.stateCode, //
                    orderHeader.stateReason, //
                    orderHeader.testNumber0,
                    orderHeader.testNumber1
                    )); //

Запрос не выполняется при попытке установить orderTypeCode в DTO (stateCode dito).
Это сущность:

  @Entity
  @Table(name = "ORDERHEADER", uniqueConstraints = { @UniqueConstraint(columnNames = { "orderCode" }) })
  public class OrderHeader extends BaseEntity {

      protected String orderGroup;            // no problem
      protected OrderTypeCode orderTypeCode;  // illegal argument type when calling setter
      protected OrderHeaderState stateCode;   // illegal argument type when calling setter
      protected float testNumber0;
      protected double testNumber1;

      public OrderHeader() {
          //DO NOT REMOVE. REQUIRED BY HIBERNATE.
      }

      public OrderHeader(OrderHeaderDTO dto) {

          super(dto);

          orderGroup = dto.getOrderGroup();
          orderTypeCode = dto.getOrderTypeCode();
          stateCode = dto.getStateCode();
          testNumber0 =  dto.getTestNumber0();
          testNumber1 = dto.getTestNumber1();
      }

      @Override
      @Id
      @Column(name = "ID")
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HibSOrderheader")
      @SequenceGenerator(name = "HibSOrderheader", sequenceName = "SOrderheader", allocationSize = 1)
      public long getId() {
          return id;
      }

      @Size(max = 30)
      @Column(name = "ORDERGROUP", length = 30)
      public String getOrderGroup() {
          return orderGroup;
      }

      public void setOrderGroup(String orderGroup) {
          this.orderGroup = orderGroup;
      }

      @Enumerated(EnumType.STRING)
      @Column(name = "ORDERTYPECODE")
      public OrderTypeCode getOrderTypeCode() {
          return orderTypeCode;
      }

      public void setOrderTypeCode(OrderTypeCode orderTypeCode) {
          this.orderTypeCode = orderTypeCode;
      }

      @Enumerated(EnumType.STRING)
      @Column(name = "STATECODE", columnDefinition = "varchar2(20)")
      public OrderHeaderState getStateCode() {
          return stateCode;
      }

      protected void setStateCode(OrderHeaderState stateCode) {
          this.stateCode = stateCode;
      }

      @Column(name = "TESTNUMBER0")
      public float getTestNumber0() {
          return testNumber0;
      }

      public void setTestNumber0(float testNumber0) {
          this.testNumber0 = testNumber0;
      }

      @Column(name = "TESTNUMBER1")
      public double getTestNumber1() {
          return testNumber1;
      }

      public void setTestNumber1(double testNumber1) {
          this.testNumber1 = testNumber1;
      }

  } 

и перечисление:

   public enum OrderTypeCode {
        NORMAL,
        INVENTORY,
        TRANSFER,
        RELOCATE
    }

и DTO:

    public class OrderHeaderDTO extends BaseEntityDTO {

        private String orderGroup;
        private OrderTypeCode orderTypeCode;
        private OrderHeaderState stateCode;
        private float testNumber0;
        private double testNumber1;

        public OrderHeaderDTO() {
            super();
        }

        @QueryProjection
        public OrderHeaderDTO(IBaseEntity base, String orderCode,
                String orderGroup, OrderTypeCode orderTypeCode, int hostId, int priority, String creationMode,
                String shippingMode, String stagingArea, Date requestedDeliveryTime, String deliveryNote,
                String deliveryCode, String customerCode, String customerOrderCode, String headerText,
                OrderHeaderState stateCode, String stateReason, Date stateTime, List<OrderPositionDTO> orderPosition, float testNumber0,
        double testNumber1) {
            super(base);
            this.orderGroup = orderGroup;
            this.orderTypeCode = orderTypeCode;
            this.stateCode = stateCode;
            this.testNumber0 = testNumber0;
            this.testNumber1 = testNumber1;
        }

        @QueryProjection
        public OrderHeaderDTO(long id, long version, Date creationTime, Date lastUpdateTime,
                String orderGroup, OrderTypeCode orderTypeCode, OrderHeaderState stateCode,
                float testNumber0, double testNumber1) {
            super(id, version, creationTime, lastUpdateTime);
            this.orderGroup = orderGroup;
            this.orderTypeCode = orderTypeCode;
            this.stateCode = stateCode;
            this.testNumber0 = testNumber0;
            this.testNumber1 = testNumber1;
        }

        /**
         * Copy constructor (shallow copy)
         * @param arg Original value
         */
        public OrderHeaderDTO(OrderHeaderDTO arg) {
            super(arg);
            orderGroup = arg.orderGroup;
            orderTypeCode = arg.orderTypeCode;
            creationTime = arg.creationTime;
            stateCode = arg.stateCode;
            testNumber0 = arg.testNumber0;
            testNumber1 = arg.testNumber1;
        }

        public String getOrderGroup() {
            return orderGroup;
        }

        @Enumerated(EnumType.STRING)
        public OrderTypeCode getOrderTypeCode() {
            return orderTypeCode;
        }

        public OrderHeaderState getStateCode() {
            return stateCode;
        }
        public void setOrderGroup(String orderGroup) {
            this.orderGroup = orderGroup;
        }

        public void setOrderTypeCode(OrderTypeCode orderTypeCode) {
            this.orderTypeCode = orderTypeCode;
        }
        public void setStateCode(OrderHeaderState stateCode) {
            this.stateCode = stateCode;
        }

        public float getTestNumber0() {
            return testNumber0;
        }

        public void setTestNumber0(float testNumber0) {
            this.testNumber0 = testNumber0;
        }

        public double getTestNumber1() {
            return testNumber1;
        }

        public void setTestNumber1(double testNumber1) {
            this.testNumber1 = testNumber1;
        }

    }

и, наконец, трассировка стека выбрасывается:

      org.springframework.dao.InvalidDataAccessApiUsageException: argument type mismatch; nested exception is java.lang.IllegalArgumentException: argument type mismatch
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:296)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:107)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at com.sun.proxy.$Proxy55.searchOrderWithInfoForCriteria(Unknown Source)
    at com.stoecklin.wms.dbunittest.implementation.repository.OrderHeaderCustomRepoIT.test_noCriteria(OrderHeaderCustomRepoIT.java:188)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
  Caused by: java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.mysema.util.BeanMap.put(BeanMap.java:330)
    at com.mysema.util.BeanMap.put(BeanMap.java:51)
    at com.mysema.query.types.QBean.newInstance(QBean.java:250)
    at com.mysema.query.support.NumberConversions.newInstance(NumberConversions.java:65)
    at com.mysema.query.jpa.FactoryExpressionTransformer.transformTuple(FactoryExpressionTransformer.java:50)
    at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:95)
    at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:431)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2342)
    at org.hibernate.loader.Loader.list(Loader.java:2337)
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338)
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1827)
    at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:231)
    at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:157)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:268)
    at com.mysema.query.jpa.sql.AbstractJPASQLQuery.getResultList(AbstractJPASQLQuery.java:193)
    at com.mysema.query.jpa.sql.AbstractJPASQLQuery.list(AbstractJPASQLQuery.java:224)
    at com.stoecklin.wms.repository.implementation.OrderHeaderRepositoryImpl.searchJPASQLIntoDTO(OrderHeaderRepositoryImpl.java:347)
    at com.stoecklin.wms.repository.implementation.OrderHeaderRepositoryImpl.searchOrderWithInfoForCriteria(OrderHeaderRepositoryImpl.java:517)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:344)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
    ... 37 more

Вот теперь вопросы:

  1. Как мы можем предоставить выражения преобразования типов для некоторых столбцов, а именно перечисления, в проекциях?
  2. Можно ли использовать сгенерированные метаданные сущности (из apt-maven-plugin) для JPASQL?

Любая помощь приветствуется.

Я также исследовал различные другие варианты с не намного лучшими результатами:

  1. Использование собственных метаданных SQL (из querydsl-maven-plugin) для проекции не сильно изменилось, но выявило дополнительные проблемы с отображением типов.
  2. Выбор из собственных метаданных SQL имел такое же поведение.
  3. Проектирование в сущность работает, но это не является намерением, потому что мы хотим напрямую заполнять DTO (также синтезированными значениями). Если мы используем сущности, то мы должны потом скопировать сущность в DTO.

РЕДАКТИРОВАТЬ: Используемые версии:

QueryDSL: 3.2.4
Весна: 3.2.2. ВЫПУСК
Hibernate:4.2.6.Final

Последний запрос, который мы хотим использовать, должен быть таким (только SQL):

   SELECT
   oh.*,
   (select count(id)                 -- correlated subquery
      from orderposition p
     where p.orderHeaderID = oh.id) as nofPosPerOrder,
   og.mostImportantPrioInGroup,
   og.earliestDeliveryTime,
   og.earliestCreationTime
  FROM orderHeader oh LEFT JOIN      -- left join with aggregating query for order group
       (SELECT g.orderGroup,
               min(g.priority)             as mostImportantPrioInGroup,
               min(g.requestedDeliveryTime as earliestDeliveryTime,
               min(g.requestedCreationTime as earliestCreationTime
          FROM orderHeader g
          GROUP by g.orderGroup) og
     ON oh.orderGroup = og.orderGroup
  WHERE ?????
  ORDER BY .

0 ответов

Другие вопросы по тегам