【问题标题】:How to transform a flat result set using Hibernate如何使用 Hibernate 转换平面结果集
【发布时间】:2016-07-21 13:13:33
【问题描述】:

是否可以将 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;
}

【问题讨论】:

    标签: java hibernate hibernate-criteria


    【解决方案1】:

    是的,这是可能的。您可以为此使用自定义转换器: FluentHibernateResultTransformer.

    您可以复制粘贴代码,或通过Maven添加jar:fluent-hibernate-core。

    您需要将Criteria 与Projections 一起使用。请不要忘记指定投影别名(userName、addressDetails.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 一起使用

    不可能将它与 HQL 一起使用,因为 Hibernate 不允许在 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();
    

    【讨论】:

    • 非常感谢您这么快的回复。这是我需要的。
    • 太棒了,但这不适用于当你有一个 Set ,对象 Child 扩展 Parent,并且你只想要 Child 的特定字段时,它会抛出 parent 没有的异常有这样的属性,它不处理继承。有什么解决办法吗?
    • @hocikto 它应该可以工作。可能你的集合有Parent 而不是Child。如果不是这样,您可以使用示例添加问题 github.com/v-ladynev/fluent-hibernate/issues
    • @v.ladynev 我发现问题是,流利的人试图为返回 Set 的字段找到一个 setter。在您的类 NestedSetter 中,您在代码 class.getSuperClass() 中调用某处,它正在寻找 Set 的超类而不是“Somethings”超类。我设法使用泛型从 Set 中获取对象类型,但由于我在应用程序中遇到的其他问题,它最终根本没有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 2013-09-28
    • 2011-06-17
    相关资源
    最近更新 更多