Java Hibernate使用addEntity创建SQLQuery

Java Hibernate使用addEntity创建SQLQuery,java,hibernate,Java,Hibernate,我需要对此应用一个类似的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 b

我需要对此应用一个类似的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);
}
这个查询还可以。返回一个我可以迭代的对象数组,但我想返回一个Student对象,所以我添加了

   .addEntity(Student.class)
但有一个错误是

Column 'ACTIVE' not found.
我也尝试了.addScalar,但同样的情况也发生了

.addScalar("id",org.hibernate.type.IntegerType.INSTANCE)
.addScalar("c03",org.hibernate.type.DateType.INSTANCE)
这是一个来自Student的专栏,但不在投影上。我的问题是如何做到这一点,我只是认为以某种方式应用别名将休眠填充Student实体

我只需要一个id为c03、c34的学生对象


我做错的是这是可能的?

对于这个用例,您不希望hibernate将Student视为一个实体,而是一个DTO

为此,不要使用
addEntity
方法,而是使用
setresulttransfer

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,并且没有arg构造函数。我从未在实体类上测试过这个

如果没有setter,但有这3个字段的构造函数,则可以使用:

// choose here the right constructor
java.lang.reflect.Constructor constructor = Student.class.getConstructors()...
// ...
.setResultTransformer(new AliasToBeanConstructorResultTransformer(constructor));
相反

编辑: 我不会将实体用作DTO(但会为此用例创建一个特定的DTO):如果您的一个服务认为该实体是以常规方式加载的(因此完全初始化),对其进行一些修改(例如更新字段),然后保存该实体,该怎么办

在最好的情况下,一个不可为null的字段(在db端)将不会被初始化,您将得到一个ConstraintViolationException并触发回滚,从而保证数据的安全


在最坏的情况下,将实体的所有字段设置为
null
,除了三个已加载的字段之外,都会损坏数据。

请参见下面的答案,但最简单的方法是从学生表中选择所有列(即选择*)。然后你可以得到你的实体。从性能角度来看,选择几个额外的列很少有什么大不了的。