How to make custom projection with the Criteria API in NHibernate?

Using HQL, I can use dynamic instance creation as follows:

select new ItemRow(item.Id, item.Description, bid.Amount) from Item item join item.Bids bid where bid.Amount > 100 

Now I need to dynamically create my queries using the criteria API. How to get the same results that I would get using HQL, but using the criteria API?

Thanks.

+4
source share
3 answers

You can use the AliasToBean results transformer. ( Doc 1.2 ) It assigns to each projection a property with the same name.

 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(); 
+7
source

Assuming you are using NHibernate 2.0.1 GA, here is the relevant documentation:

http://nhibernate.info/doc/nh/en/index.html#querycriteria-projection

Hope this helps!

+1
source

When you use projection, the return type becomes the object or object [] instead of the criteria type. You must use a transformer.

Here is a simple 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; } } 

Here's how you use it:

 ProjectionList pl = (...) String[] projection = new String[]{"Id","Description","Bid.Amount"}; crit.setProjection(pl).setResultTransformer(new ProjectionTransformer(projection)); 

I have not tested it for a relationship (e.g. Bid.Amount).

+1
source

All Articles