对于这种用例,您不希望hibernate将Student视为实体,而是作为DTO.
为此,不要使用addEntity方法,而是setResultTransfomer:
final List result = currentSession()
.createsqlQuery("SELECT id as id,c34 as c34 " +
"FROM (SELECT id,c03 FROM students " +
"where c34 in(:filters) " +
"order by id desc) o group by c34")
.setParameterList("filters",1812))
.addScalar("id",org.hibernate.type.IntegerType.INSTANCE)
.addScalar("c03",org.hibernate.type.DateType.INSTANCE)
.addScalar("c34",org.hibernate.type.DateType.INSTANCE)
.setResultTransformer(Transformers.aliasToBean(Student.class))
.list();
这对于非实体类是有效的,只要类具有与投影列的名称相匹配的setter,并且有一个无参数构造函数.我从来没有在实体类上测试过这个.
如果您没有setter,而是这3个字段的构造函数,可以使用:
// choose here the right constructor
java.lang.reflect.Constructor constructor = Student.class.getConstructors()...
// ...
.setResultTransformer(new AliasToBeanConstructorResultTransformer(constructor));
代替.
编辑:
我不会使用一个实体作为一个DTO(但是为这个用例创建一个特定的DTO):如果你的一个服务认为实体被加载了一个正常的方式(所以被完全初始化),做一些修改(更新一个字段为例),并保存实体?
在最好的情况下,不可空字段(在db端)将不会被初始化,您将收到一个ConstraintViolationException并触发回滚,从而保持数据的安全.
在最坏的情况下,您将通过将实体的所有字段设置为null,而将三个已加载的字段设置为null来破坏数据.