问题
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?
回答1:
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 ..."
来源:https://stackoverflow.com/questions/39497294/custom-type-converter-in-conjunction-with-hibernates-transformers-aliastobean