2009-04-05 9 views
4

С HQL я могу использовать динамический экземпляр, как это:Как сделать пользовательскую проекцию с помощью API критериев в NHibernate?

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

Теперь мне нужно, чтобы создать свои запросы динамически с Criteria API. Как получить те же результаты, которые я получил бы с помощью HQL, но используя API критериев?

спасибо.

ответ

1

При использовании проекции возвращаемый тип становится объектом или объектом [] вместо типа критериев. Вы должны использовать трансформатор.

Вот простой 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).

7

Вы можете использовать трансформатор результатов 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(); 
+0

Спасибо за этот простой драгоценный камень! –