I am having a problem with Hibernate HQL Projection using the AliasToBeanResultTransformer, basically the result I am trying to return isn't being mapped properly to the bean, here is the situation:
The HQL query that I am using is this:
select entity.categoryTypes as categoryTypes from nz.co.doltech.ims.server.entities.IncidentEntity entity where (entity.id = :id105019)
I want to get the CategoryType
's from the IncidentEntity
based on its join relationship. This works fine when I'm not attempting to use any transformer on it. categoryTypes
is a Set and the transformer keeps trying to check the Method's parameter types and fails because instead of finding a CategoryTypeEntity
it finds a java.util.Set
as if its trying to map a single CategoryTypeEntity
into the categoryTypes
field. I would have thought that because its a Set it would pull the data out as a Set
and then try map it to the categoryTypes
field. Apparently not though.
@javax.persistence.Entity(name = "incidents")
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL)
public class IncidentEntity implements Entity {
...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "incident_categorytype", joinColumns = {
@JoinColumn(name = "incident_id", nullable = false, updatable = false) },
inverseJoinColumns = {
@JoinColumn(name = "categorytype_id", nullable = false, updatable = false)
})
private Set<CategoryTypeEntity> categoryTypes = new HashSet<CategoryTypeEntity>();
...
public Set<CategoryTypeEntity> getCategoryTypes() {
return categoryTypes;
}
public void setCategoryTypes(Set<CategoryTypeEntity> categoryTypes) {
this.categoryTypes = categoryTypes;
}
}
Here is the call I make:
Query query = session.createQuery("select entity.categoryTypes as categoryTypes from nz.co.doltech.ims.server.entities.IncidentEntity entity " +
"where (entity.id = :id105019)")
query.setResultTransformer(Transformers.aliasToBean(IncidentEntity.class));
return query.list();
The exceptions I get are:
Caused by: org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of nz.co.doltech.ims.server.entities.IncidentEntity.categoryTypes
...
Caused by: java.lang.IllegalArgumentException: argument type mismatch
And the hibernate log message is:
Jun 27, 2014 12:32:11 AM org.hibernate.property.BasicPropertyAccessor$BasicSetter set
SEVERE: IllegalArgumentException in class: nz.co.doltech.ims.server.entities.IncidentEntity, setter method of property: categoryTypes
Jun 27, 2014 12:32:11 AM org.hibernate.property.BasicPropertyAccessor$BasicSetter set
SEVERE: expected type: java.util.Set, actual value: nz.co.doltech.ims.server.entities.CategoryTypeEntity
Using Hibernate 3.6.10
Can anyone see what is going on here? It really doesn't seem like normal behavior, perhaps I have done something wrong. Would appreciate any help I can get!
UPDATE: This is strange, not directly related to the issue. When I have hibernates use_query_cache property set to true I keep getting the projection result as null in the AliasToBeanResultTransformer (then the result returns as null (or [null, null, null] depending on how many are returned. I think this might be a bug? In regards to the issue at hand, when I remove the result transformer it returns 3 CategoryTypeEntites
as expected. When its added I get one CategoryTypeEntity that's being processed in the Transformers transformTuple method. Really confused about both of these issues.
Cheers, Ben
Manage to resolve this issue by rewriting the AliasToBeanResultTransformer class. It will not insert into a collection if the collection types match and the collections generic type match. I also found a great nested bean transformer make by samiandoni that will allow me to map nested projection values too :) Here is how I implemented it for anyone else having this same issue:
You will need to implement this RefectUtil method too:
Then you can make it work with samiandoni's transformer too (just ensure its using your edited AliasToBeanResultTransformer class):