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

问题描述

继续关注昨天发布的问题:



有人可以告诉我一个如何在Hibernate中对以下SQL进行编码并获得正确结果的示例吗? / p>

SQL:

 选择名字,姓氏$ b $ from Employee 

如果可能在Hibernate中,我想要做的是将结果放入其中自己的基类:

  class结果{
private firstName;
私人姓氏;
// getters和setters
}

我相信在JPA使用 EntityManager ),但我还没有想出如何在Hibernate中执行它(使用 SessionFactory Session )。



我试图更好地学习Hibernate,即使这个简单的查询也很难理解Hibernate返回结果,以及如何将结果映射到我自己的(基类)类中。所以在DAO例程结束时,我会这样做:

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

返回 List of 结果(我的基类)。

解决方案
 从Employee 

中选择firstName,lastName 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无法在org.hibernate.property.access.internal.PropertyAccessMapImpl $ SetterImpl.set(PropertyAccessMapImpl.java:102)
p $ p>

问题在于,Hibernate将列名的别名转换为大写 - firstName 变为 FIRSTNAME 。它试图在<$ c $>中找到名为 getFIRSTNAME()和setter setFIRSTNAME()的getter c> DTO 使用这种策略

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

只有 PropertyAccessStrategyMapImpl.INSTANCE Hibernate,好吧。所以之后它会尝试转换(Map)MyResults

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

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



如何解决
$ b

在引号中使用别名

  public class Results {

private String firstName;

私人字符串姓氏;

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\来自员工;

列表<结果> employees = session.createSQLQuery(sql).setResultTransformer(
Transformers.aliasToBean(Results.class))。list();

使用自定义结果转换器



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

只需从项目页面下载库(它不需要额外的jar):。

 字符串sql =select firstName,lastName来自员工; 
列表<结果> employees = session.createSQLQuery(sql)
.setResultTransformer(new FluentHibernateResultTransformer(Results.class))
.list();

该转换器也可用于嵌套投影:


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

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

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
}

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

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();

returning a List of Results (my base class).

解决方案
select firstName, lastName from Employee

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

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)

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
    );

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.

How to solve

Using aliases with quotes

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();

Using a custom result transformer

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

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();

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

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

09-05 04:48