2013-05-15 12 views
6

Próbuję użyć GROUP BY w moich kryteriach. Muszę to zrobić:Kryterium hibernacji Korzystanie z GROUP BY i POWRÓT LISTY ENTITY

SELECT b FROM Book b GROUP BY volumeCode; 

Mam następujący kod:

Criteria c = s.createCriteria(Book.class); 
    c.setProjection(Projections.projectionList().add(Projections.groupProperty("volumeCode"))); 
    List<Book> result = c.list(); 

Ale to kryteria zwraca tylko volumeCode s (listę ciągów). Muszę uzyskać listę Book s. Dlatego próbowałem użyć Transformers:

Criteria c = s.createCriteria(Book.class); 
    c.setProjection(Projections.projectionList().add(Projections.groupProperty("volumeCode"))); 
    c.setResultTransformer(Transformers.aliasToBean(Book.class)); 
    List<Book> result = c.list(); 

Ten kod zwraca listę wartości pustych. Czy można to zrobić za pomocą kryteriów?

Odpowiedz

5

Po pierwsze, projektor filtruje ilość odzyskanych danych, jeśli chcesz więcej danych, dodaj te właściwości do projekcji.

Przykład:

c.setProjection(Projections.projectionList() 
    .add(Projections.property("id").as("id")) 
    .add(Projections.property("descripction").as("description")) 
    .add(Projections.groupProperty("volumeCode").as("volumeCode"))); 

Teraz transformator robi to, co mówi "Alias ​​do Bean", robi się mecz alias z właściwościami swojej java fasoli "Book.java".

Edit:

Bez transformatora, jeśli projekcja ma więcej niż jedną właściwość, wynik wychodzi tak:

for(Object[] item:criteria.list()){ 
    System.out.println((String)item[0]); //ID 
    System.out.println((String)item[1]); //Description 
    System.out.println((String)item[2]); //Volume code 
} 

To dlaczego pan się wyjątek odlewu, o transformatora, spróbuj dopasować każdy alias do nazwy właściwości twojego komponentu bean Java.

+0

Witaj Ziul, thx za odpowiedź. Z twoją radą otrzymuję List obiektów, ale Java zgłasza wyjątek, kiedy próbuję rzucić dowolny obiekt z listy do Księgi. –

+0

Ehm, usuwam linię z transformatorem O: -) ... Po dodaniu tego wiersza nadal otrzymuję Listę obiektów zerowych. –

+0

Dziękujemy za edytowanie wpisu. Nie chcę dostać tylko jednej własności, ale cały obiekt. Potrzebuję uzyskać tę samą listę obiektów, jak po wywołaniu 'SELECT b FROM Book b GROUP BY volumeCode', więc wynikiem powinien być List

2

myślę, że można użyć: criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

+0

Myślisz? Czemu? W jaki sposób? – rayryeng

+1

@rayryeng Napotykam ten sam problem, próbując uzyskać 'WYBIERZ p od osoby p GROUP BY personId' przy użyciu kryteriów, ale używając setProjection to po prostu przekonwertuj go do sql odpowiednik' wybierz distint (personId) od osoby' i zwróć listę personId wheres i potrzebny jest cały obiekt osoby i lista "List = session.createCriteria (" Person "," p ") .setResultTransformer (Criteria.DISTINCT_ROOT_ENTITY); Zwróć listę obiektu osoby. co do tego, dlaczego i jak nadzieja to pomoże [tutaj] (http://stackoverflow.com/questions/10961048/setresulttransformer-in-criteria) – Mazrul

+0

Dodaj to do swojego posta. Nie wiedzieliśmy, dlaczego to na początku ci pomogło – rayryeng

3

cz_Nesh. Przepraszam za moją pierwszą odpowiedź. Czytam api Hibernate i czytam kod źródłowy Hibernacji, który znajduję. jeśli użyć tego kodu

session.createCriteria(EmpUserImpl.class).list(); 

powróci listy EmpUserImpl. jeśli użyć tego kodu

 criteria.setProjection(Projections.projectionList() 
      .add(Projections.groupProperty("company").as("company")) 
      .add(Projections.property("name").as("name")) 
      .add(Projections.property("company").as("company"))); 
     List list = criteria.list(); 

Lista będzie powrócić, nie listy EmpUserImpl dlaczego? Widzę, że kryterium klasy nadrzędnej kryterium KryteriaSpecyfikacja znajduje.

public interface CriteriaSpecification { 

/** 
* The alias that refers to the "root" entity of the criteria query. 
*/ 
public static final String ROOT_ALIAS = "this"; 

/** 
* Each row of results is a <tt>Map</tt> from alias to entity instance 
*/ 
public static final ResultTransformer ALIAS_TO_ENTITY_MAP = AliasToEntityMapResultTransformer.INSTANCE; 

/** 
* Each row of results is an instance of the root entity 
*/ 
public static final ResultTransformer ROOT_ENTITY = RootEntityResultTransformer.INSTANCE; 

/** 
* Each row of results is a distinct instance of the root entity 
*/ 
public static final ResultTransformer DISTINCT_ROOT_ENTITY = DistinctRootEntityResultTransformer.INSTANCE; 

/** 
* This result transformer is selected implicitly by calling <tt>setProjection()</tt> 
*/ 
public static final ResultTransformer PROJECTION = PassThroughResultTransformer.INSTANCE; 

/** 
* Specifies joining to an entity based on an inner join. 
* 
* @deprecated use {@link org.hibernate.sql.JoinType#INNER_JOIN} 
*/ 
@Deprecated 
public static final int INNER_JOIN = JoinType.INNER_JOIN.getJoinTypeValue(); 

/** 
* Specifies joining to an entity based on a full join. 
* 
* @deprecated use {@link org.hibernate.sql.JoinType#FULL_JOIN} 
*/ 
@Deprecated 
public static final int FULL_JOIN = JoinType.FULL_JOIN.getJoinTypeValue(); 

/** 
* Specifies joining to an entity based on a left outer join. 
* 
* @deprecated use {@link org.hibernate.sql.JoinType#LEFT_OUTER_JOIN} 
*/ 
@Deprecated 
public static final int LEFT_JOIN = JoinType.LEFT_OUTER_JOIN.getJoinTypeValue(); 

}

widać public static ostateczną ResultTransformer PROJECTION? mówi, że ten wynikowy transformator jest wybierany niejawnie przez wywołanie metody setProjection() oznacza, że ​​gdy używasz kryterium.setProjection, wynik nie będzie zawierał listy EmpUserImpl, ponieważ ResultTransformer zmienia się na "PROJEKCJA" z "ROOT_ENTITY" .zostanie zapakowane przez rzutowanie (jak wybierz nazwę, oid ..). , więc jeśli chcesz zwrócić listę EmpUserImpl, musisz ustawić Projections.property ("name"). As ("name")., (Jeśli potrzebujesz nazwy właśnie ustawić nazwę). to jest mój kod.

 Criteria criteria = session.createCriteria(EmpUserImpl.class); 
    criteria.setProjection(Projections.projectionList() 
      .add(Projections.groupProperty("company").as("company")) 
      .add(Projections.property("name").as("name")) 
      .add(Projections.property("company").as("company"))); 
    criteria.setResultTransformer(Transformers.aliasToBean(EmpUserImpl.class)); 
    List<EmpUserImpl> list = criteria.list(); 
    for (EmpUserImpl empUserImpl : list) { 
     System.out.println(empUserImpl.getName()); 
    } 

może działać. mam nadzieję, że może ci pomóc.