我正在尝试使用包装类作为结果类型来进行查询。抱歉我的帖子有点长,但我想尽可能完整地提出我的问题。 根类有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。 我在网上搜索,但是找不到有人试图检索多个列表。 我是否漏掉了一些明显的东西?多个获取操作是不可取的(hibernate bug),而且我也不能使列表变成Eager。 另一个相关的问题是: 我能否创建一个查询,使我的包装类的列表也是实体的包装器而不是实体本身?(例如:不使用Cashiers,只获取名字和姓氏,并使用包含这两个字符串的CashierWrapper列表) 非常感谢您,希望您能帮助我。