自定义类型/转换器与Hibernate的Transformers.aliasToBean一起使用

时间:2016-09-14 18:29:02

标签: java hibernate grails

我正在Hibernate中执行本机查询,我想将结果集转换为MyDto列表。

使用本机查询时,我们通常遵循以下模式:

String query = "SELECT first_name as firstName, birth_date as birthDate ..."

def results = session.createSQLQuery(query)
    .setResultTransformer(Transformers.aliasToBean(MyDto.class))
    .list();

问题是我们在我们的日期类中使用Joda-time(在这种情况下,birthDate是一个LocalDate)。使用普通的Hibernate查询,这很好(我们有自己的简单UserTypes)。但是对于本机查询,我们通常使用java.util.Date作为Dto类的变通方法。我希望在我们的Dtos中保持Joda类型(LocalDate,Instant等)与我们的实体保持一致。

我在网上找到了一个解决方法:

// GrailsLocalDate is our custom UserType class for joda's LocalDate class
Type localDateType = new TypeLocatorImpl(
    new TypeResolver()).custom(GrailsLocalDate.class);

def results =  session.createSQLQuery(query)
    .addScalar("birthDate", localDateType)
    .setResultTransformer(Transformers.aliasToBean(CorrespondentAssociateDto.class))
    .list()

问题是,一旦我调用addScalar,它似乎改变了我必须使用addScalar调用指定所有列的行为。因此,如果我的查询选择10-15列,我需要添加10-15个addScalar调用。然而,如果我没有任何自定义转换,我不需要任何addScalar调用,而aliasToBean只是根据匹配结果集别名映射到DTO的字段名称。我希望我可以为给定列指定一个变换器,然后aliasToBean将照常使用其他变换器。

有没有人做过类似的事情?

1 个答案:

答案 0 :(得分:0)

我找到了一个更简单的解决方法,我可以简单地将setter添加到我的Dto中:

public void setBirthDate(java.util.Date d) {
    if (d == null) {
        this.birthDate = null;
    } else {
        this.birthDate = new LocalDate(d.getTime());
    }
}

...当然你可以把它包装成一个实用工具方法。

编辑:这导致我们正在执行的代码中的其他地方出现问题:

myDto.birthDate = someLocalDate // implicitly calls setBirthDate(java.util.Date).

修复程序正在更改我的setter名称:

public void setCustomSetterForBirthDate(...

在我的查询中,我将birth_date列别名为customSetterForBirthDate:

String query = "SELECT ..., birth_date as customSetterForBirthDate ..."