【问题标题】:How to work around Hibernate 5 requiring compatible constructor for selected fields?如何解决 Hibernate 5 需要为选定字段提供兼容的构造函数?
【发布时间】:2018-01-01 09:45:17
【问题描述】:

我已将我的应用程序从 Hibernate 3 升级到 5.2.10。 Hibernate 的标准已被弃用,因此我修改了我的代码以使用 JPA 标准。

问题在于 Hibernate 需要在 DTO 类中为所选字段指定一个特定的构造函数。

在 Hibernate 3 中,在使用投影和 setResultTransformer(new AliasToBeanResultTransformer(MyDTO.class)) 时,一个空的构造函数和一个 getter/setter 对足以将结果映射到 DTO。

    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<MyDTO> criteria = builder.createQuery(MyDTO.class);
    Root<MyEntity> root = criteria.from(MyEntity.class);
    criteria.multiselect(root.get(MyEntity_.id).get(MyEntityId_.fieldToSelect));
    return getEntityManager().createQuery(criteria).getResultList();

我遇到了这个异常:

java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [MyDTODTO]. Expected arguments are: java.lang.String [select new MyDTODTO(generatedAlias0.fieldToSelect) from MyEntity as generatedAlias0]

根据javadoc,这是正常的:

如果某个用户定义的类 X 的条件查询类型为 CriteriaQuery&lt;X&gt;(即,通过将 X 类参数传递给 createQuery 方法创建的条件查询对象),则将列表的元素传递给多选方法将被传递给 X 构造函数,并且将为每一行返回一个 X 类型的实例。

如果我使用,我也会遇到同样的问题:

criteria.select(builder.construct(MyDTO.class, field1,.., fieldn)

我的 DTO 可以被不同的查询使用我不想为不同的查询创建不同的构造函数。

我可以避免创建兼容的构造函数吗?

【问题讨论】:

  • 嗨,@rawadolb,我在这里遇到了同样的问题,你有没有找到任何关于这个的问题?
  • 嗨@cingulata..不,我没有..我正在使用queryDsl来避免这个问题
  • 你能分享一个样本吗?嵌套对象呢?
  • 两种意见: 1.如果两个查询选择不同的值,它们不应该返回相同类型的对象。 2. 无论如何,我发现将结果作为 List 并将每个数组显式映射到一个对象更简洁。它使重构代码更加安全。
  • @cingulata :抱歉延迟回复。在这里查看我的答案

标签: hibernate projection criteria-api


【解决方案1】:

最后我正在使用 QueryDsl 框架。它非常易于使用和集成到我的应用程序中。

您应该生成元模型类,然后您可以轻松编写您的请求。请查看此示例:https://github.com/querydsl/querydsl/issues/266

这是另一个嵌套对象(EjAffaire、EjPartie 和 EjDebiteur)的示例。

    QEjAffaire ejAffaire = QEjAffaire.ejAffaire;
    QEjPartie ejPartie = QEjPartie.ejPartie;
    QEjDebiteur ejDebiteur = QEjDebiteur.ejDebiteur;
    return new JPAQueryFactory(getEntityManager()).selectFrom(ejPartie).join(ejPartie.ejAffaire, ejAffaire)
        .join(ejPartie.ejDebiteurs, ejDebiteur)
        .where(ejPartie.id.jpaGrNume.eq(ejSuiDel.getJsdGrNume())
            .and(ejPartie.jpaRcsGrNume.coalesce(ejPartie.id.jpaGrNume).getValue().eq(result))
            .and(ejPartie.jpaRcsMil.eq(ejSuiDel.getJsdRcsMil()).and(ejPartie.jpaRcsStC.eq(ejSuiDel.getJsdRcsStC()))
                .and(ejPartie.jpaRcsChrono.eq(ejSuiDel.getJsdRcsChrono())).and(ejPartie.id.jpaQpC.eq("DF"))
                .and(ejAffaire.jafTaC.eq("J"))
                .and(ejAffaire.jafNonRevelableOn.isFalse().or(ejAffaire.jafNonRevelableOn.isNull())))
            .and(ejDebiteur.jdbFpC.in(getFamPclReduitOn())))
        .orderBy(ejAffaire.jafSaisineD.desc()).orderBy(ejAffaire.jafGreffeD.desc())
        .orderBy(ejAffaire.jafMajD.desc()).orderBy(ejPartie.id.jpaNo.asc()).fetchFirst();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-26
    • 2011-02-25
    • 1970-01-01
    • 2014-11-22
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多