我正在尝试在我的标准中使用
GROUP BY
。我需要这样做:
SELECT b FROM Book b GROUP BY volumeCode;
我有以下代码:
Criteria c = s.createCriteria(Book.class);
c.setProjection(Projections.projectionList().add(Projections.groupProperty("volumeCode")));
List<Book> result = c.list();
但此条件仅返回
volumeCode
(字符串列表)。我需要获取 Book
的列表。所以我尝试使用变形金刚:
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();
此代码返回空值列表。是否可以通过标准来做到这一点?
首先,投影会过滤检索到的数据量,如果您想要更多数据,您也应该将这些属性添加到投影中。
示例:
c.setProjection( Projections.projectionList()
.add( Projections.property("id").as("id") )
.add( Projections.property("descripction").as("description") )
.add( Projections.groupProperty("volumeCode").as("volumeCode") ));
现在,转换器执行其所说的“Bean 别名”操作,它与 java bean“Book.java”的属性进行别名匹配。
编辑:
如果没有变压器,如果投影有多个属性,结果如下:
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
}
这就是为什么你会收到关于转换器的强制转换异常,请尝试将每个别名与你的 java bean 的属性名称相匹配。
cz_内什。 对我的第一个回答感到抱歉。 我阅读了 Hibernate api 并阅读了一些 Hibernate 源代码,我发现了这一点。 如果您使用此代码
session.createCriteria(EmpUserImpl.class).list();
它将返回List EmpUserImpl。 如果您使用此代码
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();
它会返回 List ,不是 List EmpUserImpl 为什么? 我看到该标准的父类 CriteriaSpecification 我发现。
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();
}
你能看到公共静态最终 ResultTransformer PROJECTION 吗?它说这个结果转换器是通过调用 setProjection() 隐式选择的 意思是当你使用criteria.setProjection时,结果不会列出EmpUserImpl,因为ResultTransformer从“ROOT_ENTITY”更改为“PROJECTION”。它将按Projection打包(如select name,oid ..)。 所以,如果你想返回List EmpUserImpl,你需要设置Projections.property("name").as("name").,(如果你需要name,只需设置name)。 这是我的代码。
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());
}
它可以工作。我希望它可以帮助你。
我想你可以使用:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);