简体   繁体   中英

Custom type / converter in conjunction with Hibernate's Transformers.aliasToBean

I'm executing a native query in Hibernate and I want to transform the result set into a List of MyDto's.

When using native queries, we typically follow this pattern:

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

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

The problem is we're using Joda-time for our date classes (in this case birthDate is a LocalDate). With normal Hibernate queries this is fine (we have our own simple UserTypes). But with native queries, we've typically used java.util.Date as a workaround in our Dto classes. I would prefer to keep the Joda types (LocalDate, Instant, etc.) in our Dtos to be consistent with our entities.

I found one workaround online like this:

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

The problem is that once I make a call to addScalar, it seems to change the behavior where I must specify ALL columns with addScalar calls. So if my query is selecting 10-15 columns, I need to add 10-15 addScalar calls. Whereas if I didn't have any custom transformation I don't need any addScalar calls and aliasToBean simply maps based on matching the resultset alias to the DTO's field names. I was hoping I could just specify the one transformer for the given column and then aliasToBean would the rest as usual.

Has anyone done something similar?

I found a simpler workaround, I can simply add setters to my Dto like this:

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

... and of course you could wrap that into a single utility method.


Edit: This caused problems elsewhere in the code where we were doing:

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

The fix was changing my setter name:

public void setCustomSetterForBirthDate(...

And in my query, I alias the birth_date column as customSetterForBirthDate:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM