使用 HQL,我可以像这样使用动态实例化:
select new ItemRow(item.Id, item.Description, bid.Amount)
from Item item join item.Bids bid
where bid.Amount > 100
现在我需要使用 Criteria API 动态创建我的查询。如何获得与使用 HQL 获得的相同结果,但使用 Criteria API?
谢谢你。
使用 HQL,我可以像这样使用动态实例化:
select new ItemRow(item.Id, item.Description, bid.Amount)
from Item item join item.Bids bid
where bid.Amount > 100
现在我需要使用 Criteria API 动态创建我的查询。如何获得与使用 HQL 获得的相同结果,但使用 Criteria API?
谢谢你。
您可以使用 AliasToBean 结果转换器。( Doc 1.2 ) 它将每个投影分配给同名的属性。
session.CreateCriteria(typeof(Item), "item")
.CreateCriteria("Bids", "bid")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("item.Id"), "Id" )
.Add(Projections.Property("item.Description"), "Description" )
.Add(Projections.Property("bid.Amount"), "Amount" ))
.Add(Expression.Gt("bid.Amount", 100))
.SetResultTransformer(Transformers.AliasToBean(typeof(ItemRow)))
.List();
假设您使用的是 NHibernate 2.0.1 GA,以下是相关文档:
http://nhibernate.info/doc/nh/en/index.html#querycriteria-projection
希望有帮助!
当您使用投影时,返回类型变为 Object 或 Object[] 而不是标准类型。你必须使用变压器。
这是一个简单的 ResultTransformer:
private class ProjectionTransformer implements ResultTransformer {
private String[] propertysList;
private Class<?> classObj;
/**
* @param propertysList
*/
public ProjectionTransformer(String[] propertysList) {
this.classObj = persistentClass;
this.propertysList = propertysList;
}
/**
* @param classObj
* @param propertysList
*/
public ProjectionTransformer(Class<?> classObj, String[] propertysList) {
this.classObj = classObj;
this.propertysList = propertysList;
}
@SuppressWarnings("unchecked")
public List transformList(List arg0) {
return arg0;
}
public Object transformTuple(Object[] resultValues, String[] arg1) {
Object retVal = null;
try {
retVal = Class.forName(classObj.getName()).newInstance();
int dot = -1;
for (int i = 0; i < resultValues.length; i++) {
if ((dot = propertysList[i].indexOf(".")) > 0) {
propertysList[i] = propertysList[i].substring(0, dot);
}
PropertyUtils.setProperty(retVal, propertysList[i], resultValues[i]);
}
} catch (Exception e) {// convert message into a runtimeException, don't need to catch
throw new RuntimeException(e);
}
return retVal;
}
}
以下是你如何使用它:
ProjectionList pl = (...)
String[] projection = new String[]{"Id","Description","Bid.Amount"};
crit.setProjection(pl).setResultTransformer(new ProjectionTransformer(projection));
我没有测试它的关系(例如:Bid.Amount)。