我需要应用与此类似的SQL查询.
SELECT id as id, c03 as c03, c34 as c34 FROM (SELECT id, c03, c34 FROM students where c34 in( ?, ?,?,? ) order by id desc) o group by c34;
和我的Java代码.
private final void retrieveStudents(){ final List result = currentSession() .createSQLQuery("SELECT id as id,c03 as c03,c34 as c34 FROM (SELECT id,c34,c03 FROM students where c34 in(:filters) order by id desc) o group by c34;") .setParameterList("filters",Arrays.asList(74,1812)) .list(); result.forEach(this::consumer1); }
查询就是OK.返回一个objets数组,我可以迭代,但我想返回一个Student对象,所以我添加.
.addEntity(Student.class)
但是说错误就是抛出
Column 'ACTIVE' not found.
我也试过.addScalar,但同样的事情发生了.
.addScalar("id",org.hibernate.type.IntegerType.INSTANCE) .addScalar("c03",org.hibernate.type.DateType.INSTANCE)
这是一个来自学生的专栏,但不是在投影我的问题我怎么能这样做我只是认为以某种方式应用别名将Hibernate填充学生实体.
我想要的是一个Student对象,其中填充了id,c03,c34值.
我做错了可能吗?
对于此用例,您不希望hibernate将Student视为实体,而是将其视为DTO.
为此,请不要使用该addEntity
方法,而是setResultTransfomer
:
final List result = currentSession() .createSQLQuery("SELECT id as id,c03 as c03,c34 as c34 " + "FROM (SELECT id,c34,c03 FROM students " + "where c34 in(:filters) " + "order by id desc) o group by c34") .setParameterList("filters",Arrays.asList(74,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
实体的所有字段而不是三个已加载的字段来破坏您的数据.