如何使用Hibernate转换扁平的结果集

3

是否有可能将SQL的结果映射到非扁平对象?

List<Customer> customers = hibernateSession().createCriteria(CustomerDetailsView.class)
                .add(Restrictions.in("userName", userName))
                .setProjection(buildProjection())
                .setResultTransformer(Transformers.aliasToBean(Customer.class))
                .list();

在我的情况下,CustomerDetailsView 是一个扁平的结构。但我需要将它映射到像这样的对象:
public class Customer {
    private String userName;
    private String title;
    private String firstName;
    private String lastName;
    private String type;
    private String companyName;
    private AddressDetails addressDetails;
}

并且

public class AddressDetails {
    private String countryCode;
    private String addressLine1;
    private String zipOrPostCode;
    private String city;
    private String countryDivisionName;
    private String countryDivisionCode;
    private String countryDivisionTypeCode;
    private String residentialAddress;
}
1个回答

4
是的,这是可能的。您可以使用自定义转换器:FluentHibernateResultTransformer。您可以复制粘贴代码,或通过Maven添加jar:fluent-hibernate-core。您需要使用CriteriaProjections。请不要忘记指定投影别名(userNameaddressDetails.countryCode)。
Criteria criteria = session.createCriteria(Customer.class);
criteria.createAlias("addressDetails", "addressDetails", JoinType.LEFT_OUTER_JOIN);

criteria.setProjection(Projections.projectionList()
        .add(Projections.property("userName").as("userName"))
        .add(Projections.property("addressDetails.countryCode")
        .as("addressDetails.countryCode")));

List<Customer> customers = criteria.setResultTransformer(
        new FluentHibernateResultTransformer(Customer.class)).list();

使用 HQL

由于Hibernate不允许在HQL中使用嵌套别名,因此无法与HQL一起使用。

select addressDetails.countryCode as addressDetails.countryCode

使用 addressDetails.countryCode 别名将会导致错误。

使用本地SQL

转换器可用于具有嵌套投影的本地SQL(相反于HQL)。在这种情况下需要使用带引号的别名:

String sql = "select c.f_user_name as userName, d.f_country_code as \"addressDetails.countryCode\" "
        + "from customers c left outer join address_details d on c.fk_details = d.f_pid";

List<Customer> customers = session.createSQLQuery(sql)
        .setResultTransformer(new FluentHibernateResultTransformer(Customer.class))
        .list();

非常感谢您的快速回复。这正是我所需要的东西。 - Oleksandr Samsonov
很棒,但是对于像Set<Parent>、object Child extends Parent这样的情况,如果你只想要Child的特定字段,它就会抛出一个异常,说父类没有这样的属性,它无法处理继承。有什么解决办法吗? - hocikto
@hocikto 这应该可以工作。可能是你的设置有一个Parent而不是Child。如果不是这个问题,你可以在 https://github.com/v-ladynev/fluent-hibernate/issues 上添加一个带有示例的问题。 - v.ladynev
@v.ladynev 我发现问题在于,Fluent 正在尝试查找返回 Set<Something> 的字段的 setter。在你的 NestedSetter 类中,你在代码中调用了 somewhere.getSuperClass(),它正在寻找 Set 的超类而不是 'Somethings' 的超类。我设法通过泛型从 Set 中获取对象类型,但最终由于我在应用程序中遇到的其他问题而没有用处。 - hocikto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接