带列表的JPA CriteriaQuery投影

时间:2011-09-13 15:55:31

标签: java collections jpa-2.0 projection criteria-api

我正在尝试使用包装类作为结果类型进行查询。很抱歉这篇文章很长,但我想让我的问题尽可能完整。 根类有3个我想要检索的列表:

@Entity
@Table(name = "cash")
public final class Cash extends BaseSimpleModel {
    @Id
    @SequenceGenerator(name = "id", sequenceName = "cash_seq")
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "id")
    private Long cashID;

    @Column(length = 50, unique = true)
    private String description;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "cashID")
    private List<CashAllowedValue> allowedValueList;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "cashID")
    private List<CashAllowedCurrency> allowedCurrencyList;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "cashID")
    private List<CashAllowedCashier> allowedCashierList;
    ... getters and setters
}

这是我的包装类:

public class CashQueryResult extends QueryResult {
    private Long cashID;
    private String description;
    private List<CashAllowedValue> allowedValueList;
    private List<CashAllowedCurrency> allowedCurrencyList;
    private List<CashAllowedCashier> allowedCashierList;

    public CashQueryResult(Long id, String description, List<CashAllowedValue> allowedValueList, List<CashAllowedCurrency> allowedCurrencyList, List<CashAllowedCashier> allowedCashierList)
    {
        this.cashID = id;
        this.description = description;
        this.allowedValueList = allowedValueList;
        this.allowedCurrencyList = allowedCurrencyList;
        this.allowedCashierList = allowedCashierList;
    }
    ... getters
}

这是我的疑问:

public final List<CashQueryResult> getQRList(final CashQueryParameter cashQP, final QueryHint queryHint) {
    List<CashQueryResult> cashQRL = null;
    try {
        final CriteriaBuilder cb = em.getCriteriaBuilder();
        final PredicateBuilder pb = new PredicateBuilder(cb);
        final CriteriaQuery<CashQueryResult> cq = cb.createQuery(CashQueryResult.class);
        final Root<Cash> cash = cq.from(getModelClass());

        // Joins.
        final ListJoin<Cash, CashAllowedValue> allowedValueList = cash.join(Cash_.allowedValueList, JoinType.LEFT);
        final ListJoin<Cash, CashAllowedCurrency> allowedCurrencyList = cash.join(Cash_.allowedCurrencyList, JoinType.LEFT);
        final ListJoin<Cash, CashAllowedCashier> allowedCashierList = cash.join(Cash_.allowedCashierList, JoinType.LEFT);

        // Paths.
        final Path<ValueTypeEnum> valueType = allowedValueList.get(CashAllowedValue_.valueType);
        final Path<Currency> currency = allowedCurrencyList.get(CashAllowedCurrency_.currency);
        final Path<IntranetUser> intranetUser = allowedCashierList.get(CashAllowedCashier_.cashier);

        // Expressions. Just for testing purposes.
        final Expression<List<CashAllowedValue>> cashAllowedValueListExpression = cash.get(Cash_.allowedValueList);
        final Expression<List<CashAllowedCurrency>> cashAllowedCurrencyExpression = cash.get(Cash_.allowedCurrencyList);
        final Expression<List<CashAllowedCashier>> cashAllowedCashierExpression = cash.get(Cash_.allowedCashierList);

        cq.distinct(true);
        cq.select(cb.construct(CashQueryResult.class, cash.get(Cash_.cashID), cash.get(Cash_.description),
            // cash.get(Cash_.allowedValueList), cash.get(Cash_.allowedCurrencyList), cash.get(Cash_.allowedCashierList) // does not work
            // cashAllowedValueListExpression, cashAllowedCurrencyExpression, cashAllowedCashierExpression // does not work
            allowedValueList, allowedCurrencyList, allowedCashierList // does not work
        ));

        // cq.multiselect(cash.get(Cash_.cashID), cash.get(Cash_.description),
        //     allowedValueList, allowedCurrencyList, allowedCashierList
        // ); // does not work

        cq.where(cb.and(pb.like(cash.get(Cash_.description), cashQP.getDescription()), pb.equal(valueType, cashQP.getValueType()), pb.equal(currency.get(Currency_.currencyID), cashQP.getCurrencyID()), pb.equal(intranetUser.get(IntranetUser_.agentID), cashQP.getIntranetUserID())));
        cq.orderBy(cb.asc(cash.get(Cash_.description)));

        final TypedQuery<CashQueryResult> tq = em.createQuery(cq);
        tq.setFirstResult(queryHint.getFirstResult());
        tq.setMaxResults(queryHint.getMaxResults());
        cashQRL = tq.getResultList();
    }
    catch (Throwable t) {
        throw new EJBException(t.getMessage());
    }
    return cashQRL;
}

最后,例外(它取决于我尝试的选择方法,但它总是这样):

2011-09-12 16:12:26,165 ERROR [org.hibernate.hql.PARSER] (http-127.0.0.1-8080-2) Unable to locate appropriate constructor on class [com.ebizlink.adonis.erp.model.support.CashQueryResult] [cause=org.hibernate.PropertyNotFoundException: no appropriate constructor in class: com.ebizlink.adonis.erp.model.support.CashQueryResult]
2011-09-12 16:12:26,169 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-127.0.0.1-8080-2) javax.ejb.EJBException: org.hibernate.hql.ast.QuerySyntaxException:
Unable to locate appropriate constructor on class [com.ebizlink.adonis.erp.model.support.CashQueryResult]
[select distinct new com.ebizlink.adonis.erp.model.support.CashQueryResult(generatedAlias0.cashID, generatedAlias0.description, generatedAlias1, generatedAlias2, generatedAlias3)
 from com.ebizlink.adonis.erp.model.Cash as generatedAlias0
    left join generatedAlias0.allowedValueList as generatedAlias1
    left join generatedAlias0.allowedCurrencyList as generatedAlias2
    left join generatedAlias0.allowedCashierList as generatedAlias3
 where ( 1=1 ) and ( 1=1 ) and ( 1=1 ) and ( 1=1 )
 order by generatedAlias0.description asc]

供参考,以下是PredicateBuilder以防万一。 我搜索了网络,但我找不到那些试图检索许多列表的人。 我错过了一些明显的东西吗多次抓取是不行的(休眠错误),我也不能让列表渴望。

另一个相关问题是: 我可以进行查询,我的包装类列表也是实体包装器而不是实体吗? (例如:不使用Cashiers,只需获取名字和姓氏,并使用包含两个字符串的CashierWrapper列表)

我真的很感谢你,我希望你能帮助我。

1 个答案:

答案 0 :(得分:2)

很可能你不能这样做,关于构造函数表达式的参数的说明是什么:

  

constructor_expression :: = new constructor_name(constructor_item {,constructor_item} *)   constructor_item :: =    single_valued_pa​​th_expression | scalar_expression | aggregate_expression | identification_variable

您尝试向构造函数提供的列表(collection_valued_field)不是任何constructor_item。

相关问题