将 Hibernate 查询结果映射到自定义类?

新手上路,请多包涵

跟进我昨天发布的一个问题: How to populate POJO class from custom Hibernate query?

谁能告诉我如何在 Hibernate 中编写以下 SQL 代码并正确获得结果的示例?

查询语句:

 select firstName, lastName
from Employee

如果在 Hibernate 中可能的话,我想做的是将结果放在它们自己的基类中:

 class Results {
    private firstName;
    private lastName;
    // getters and setters
}

我相信这在 JPA 中是可能的(使用 EntityManager ),但我还没有想出如何在 Hibernate 中做到这一点(使用 SessionFactorySession )。

我正在尝试更好地学习 Hibernate,即使是这个“简单”的查询也被证明令人困惑,不知道 Hibernate 以何种形式返回结果,以及如何将结果映射到我自己的(基)类中。所以在 DAO 例程结束时,我会这样做:

 List<Results> list = query.list();

返回 ListResults (我的基类)。

原文由 Chris 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 789
1 个回答
select firstName, lastName from Employee

query.setResultTransformer(Transformers.aliasToBean(MyResults.class));

由于异常,您不能将上述代码用于 Hibernate 5 和 Hibernate 4(至少是 Hibernate 4.3.6.Final)

 java.lang.ClassCastException: com.github.fluent.hibernate.request.persistent.UserDto cannot be cast to java.util.Map
    at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)

问题是 Hibernate 将列名的别名转换为大写 — firstName 变成 FIRSTNAME 。并尝试使用此类策略在 DTO --- 中找到名称为 getFIRSTNAME() 和 setter setFIRSTNAME() 的吸气剂

    PropertyAccessStrategyChainedImpl propertyAccessStrategy = new PropertyAccessStrategyChainedImpl(
            PropertyAccessStrategyBasicImpl.INSTANCE,
            PropertyAccessStrategyFieldImpl.INSTANCE,
            PropertyAccessStrategyMapImpl.INSTANCE
    );

在 Hibernate 看来,只有 PropertyAccessStrategyMapImpl.INSTANCE 适合。所以之后它会尝试进行转换 (Map)MyResults

 public void set(Object target, Object value, SessionFactoryImplementor factory) {
    ( (Map) target ).put( propertyName, value );
}

不知道,这是一个错误或功能。

怎么解决

使用带引号的别名

public class Results {

    private String firstName;

    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}

String sql = "select firstName as \"firstName\",
    lastName as \"lastName\" from Employee";

List<Results> employees = session.createSQLQuery(sql).setResultTransformer(
    Transformers.aliasToBean(Results.class)).list();

使用自定义结果转换器

另一种解决问题的方法——使用忽略方法名称大小写的结果转换器(将 getFirstName() 视为 getFIRSTNAME() )。您可以自己编写或使用 FluentHibernateResultTransformer 。您将不需要使用引号和别名(如果您的列名等于 DTO 名称)。

只需从项目页面下载库(不需要额外的 jar): fluent-hibernate

 String sql = "select firstName, lastName from Employee";
List<Results> employees = session.createSQLQuery(sql)
        .setResultTransformer(new FluentHibernateResultTransformer(Results.class))
        .list();

此转换器也可用于嵌套投影: How to transform a flat result set using Hibernate

原文由 v.ladynev 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题