2009-04-05 8 views
4

Mit HQL kann ich dynamische Instanziierung wie folgt verwenden:Wie führe ich eine benutzerdefinierte Projektion mit der Kriterien-API in NHibernate durch?

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

Jetzt brauche ich meine Anfragen dynamisch mit dem Criteria API zu erstellen. Wie kann ich die gleichen Ergebnisse erzielen, die ich mit HQL erhalten hätte, aber die Kriterien-API verwenden?

Vielen Dank.

Antwort

1

Wenn Sie eine Projektion verwenden, wird der Rückgabetyp Objekt oder Objekt [] anstelle des Kriteriumstyps. Sie müssen einen Transformator verwenden.

Hier ist ein einfaches 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; 
     } 
    } 

Hier ist, wie Sie es verwenden:

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

ich es für die Beziehungen nicht getestet haben (zB: Bid.Amount).

7

Sie können den AliasToBean-Ergebnistransformator verwenden. (Doc 1.2) Es weist jeder Projektion eine Eigenschaft mit demselben Namen zu.

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

Danke für dieses einfache Juwel! –

Verwandte Themen