将 Hibernate 查询结果映射到自定义类? [英] mapping Hibernate query results to custom class?

查看:18
本文介绍了将 Hibernate 查询结果映射到自定义类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

跟进我昨天发布的一个问题:如何从自定义 Hibernate 查询填充 POJO 类?

Following up on a question I posted yesterday: How to populate POJO class from custom Hibernate query?

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

Can someone show me an example of how to code the following SQL in Hibernate, and get the results correctly?

SQL:

select firstName, lastName
from Employee

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

What I'd like to do, if it's possible in Hibernate, is to put the results in their own base class:

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

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

I believe it's possible in JPA (using EntityManager), but I haven't figured out how to do it in Hibernate (using SessionFactory and Session).

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

I'm trying to learn Hibernate better, and even this "simple" query is proving confusing to know what form Hibernate returns the results, and how to map the results into my own (base) class. So at the end of the DAO routine, I'd do:

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

返回Results(我的基类)的List.

推荐答案

select firstName, lastName from Employee

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

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

You can't use above code with Hibernate 5 and Hibernate 4 (at least Hibernate 4.3.6.Final), because of an exception

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() 的 getter 和 setter setFIRSTNAME()

The problem is that Hibernate converts aliases for column names to upper case — firstName becomes FIRSTNAME. And it try to find a getter with name getFIRSTNAME(), and setter setFIRSTNAME() in the DTO using such strategies

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

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

Only PropertyAccessStrategyMapImpl.INSTANCE suits, in opinion of Hibernate, well. So after that it tries to do conversion (Map)MyResults.

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

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

Don't know, it is a bug or feature.

如何解决

使用带引号的别名

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 名称).

Another way to solve the problem — using a result transformer that ignores method names case (treat getFirstName() as getFIRSTNAME()). You can write your own or use FluentHibernateResultTransformer. You will not need to use quotes and aliases (if you have column names equal to DTO names).

只需从项目页面下载库(不需要额外的 jars):fluent-休眠.

Just download the library from the project page (it doesn't need additional jars): fluent-hibernate.

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

此转换器也可用于嵌套投影:如何使用 Hibernate 转换平面结果集

This transformer can be used for nested projections too: How to transform a flat result set using Hibernate

这篇关于将 Hibernate 查询结果映射到自定义类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆