Java Hibernate Transformer AliasToBeanNestedResultTransformer

我有这样的查询。 我传递学生证我需要学生以及他们父母的一些字段以及父母的一些字段 – >地址[这是我面临的主要问题]我正在使用AliasToBeanNestedResultTransformer变换器

这里是CODE的实现

这是我的代码。

 public ListsearchForStudent(Integer studentId) { Projection p=Projections.projectionList().create() .add(Projections.property("name"),"name")//the student name it works OK .add(Projections.property("lastname"),"lastname")//the student name it works OK .add(Projections.property("age"),"age")//the student AGE it works OK .add(Projections.property("p.phone"),"parent.phone")//the parent phone it works OK .add(Projections.property("address.state").as("parent.Address.state")); // i need a field from address.state here is the problem... Session session = ...... Criteria like = session.createCriteria(Student.class).add(prepareForSelect())//some filters.. .createAlias("parent","p")//the parent of the student. a student have one parent .createAlias("parent.Address","address")//the address of the parent.... a parent have one address. .setProjection(p) .setResultTransformer(new AliasToBeanNestedResultTransformer(Student.class)); Listresults=like.list(); return results; } 

它抛出

 Exception in thread "main" org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.generic.model.Parent.Address 

FYI是一些类型不匹配我已经在SAMI代码中进行了一些跟踪,我看到了这一点

 [MyState] [Address] 

看来Hibernate在这种情况下返回一个String State MyState ,变换器使用的是Address Object ,这就是type Mismatch.

是非常需要它的任何帮助

非常感谢。

我改进了SamiAndoni课程,也许它解决了你的问题

 package com.alutiiq.develop.promanagesys.core.util; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.transform.AliasToBeanResultTransformer; import org.hibernate.transform.AliasedTupleSubsetResultTransformer; import org.hibernate.transform.ResultTransformer; /** * Help to transform alises with nested alises * * @author Miguel Resendiz * */ public class AliasToBeanNestedResultTransformer extends AliasedTupleSubsetResultTransformer { private static final long serialVersionUID = -8047276133980128266L; private static final int TUPE_INDEX = 0; private static final int ALISES_INDEX = 1; private static final int FIELDNAME_INDEX = 2; private static final PropertyAccessor accessor = PropertyAccessorFactory .getPropertyAccessor("property"); private final Class resultClass; private Object[] entityTuples; private String[] entityAliases; private Map> fieldToClass = new HashMap>(); private Map> subEntities = new HashMap>(); private List nestedAliases = new ArrayList(); private Map> listFields = new HashMap>(); public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) { return false; } public AliasToBeanNestedResultTransformer(Class resultClass) { this.resultClass = resultClass; } public Object transformTuple(Object[] tuple, String[] aliases) { handleSubEntities(tuple, aliases); cleanParams(tuple, aliases); ResultTransformer rootTransformer = new AliasToBeanResultTransformer( resultClass); Object root = rootTransformer.transformTuple(entityTuples, entityAliases); loadSubEntities(root); cleanMaps(); return root; } private void handleSubEntities(Object[] tuple, String[] aliases) throws HibernateException { String fieldName = ""; String aliasName = ""; try { for (int i = 0; i < aliases.length; i++) { String alias = aliases[i]; if (alias.contains(".")) { String[] sp = alias.split("\\."); StringBuilder aliasBuilder = new StringBuilder(); for (int j = 0; j < sp.length; j++) { if (j == 0) { fieldName = sp[j]; } else { aliasBuilder.append(sp[j]); aliasBuilder.append("."); } } aliasName = aliasBuilder.substring(0, aliasBuilder.length() - 1); nestedAliases.add(alias); manageEntities(fieldName, aliasName, tuple[i]); } } } catch (NoSuchFieldException e) { throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName() + " for field name: " + fieldName + " and alias name:" + aliasName); } } private Class findClass(String fieldName) throws NoSuchFieldException, SecurityException { if (fieldToClass.containsKey(fieldName)) { return fieldToClass.get(fieldName); } else { Class subclass = resultClass.getDeclaredField(fieldName) .getType(); if (subclass.equals(List.class) || subclass.equals(Set.class)) { if (subclass.equals(List.class)) { listFields.put(fieldName, LinkedList.class); } else { listFields.put(fieldName, HashSet.class); } Field field = resultClass.getDeclaredField(fieldName); ParameterizedType genericType = (ParameterizedType) field .getGenericType(); subclass = (Class) genericType.getActualTypeArguments()[0]; } fieldToClass.put(fieldName, subclass); return subclass; } } @SuppressWarnings("unchecked") private void manageEntities(String fieldName, String aliasName, Object tupleValue) throws NoSuchFieldException, SecurityException { Class subclass = findClass(fieldName); if (!subEntities.containsKey(fieldName)) { List list = new ArrayList(); list.add(new ArrayList()); list.add(new ArrayList()); list.add(FIELDNAME_INDEX, subclass); subEntities.put(fieldName, list); } ((List) subEntities.get(fieldName).get(TUPE_INDEX)) .add(tupleValue); ((List) subEntities.get(fieldName).get(ALISES_INDEX)) .add(aliasName); } private void cleanParams(Object[] tuple, String[] aliases) { entityTuples = new Object[aliases.length - nestedAliases.size()]; entityAliases = new String[aliases.length - nestedAliases.size()]; for (int j = 0, i = 0; j < aliases.length; j++) { if (!nestedAliases.contains(aliases[j])) { entityTuples[i] = tuple[j]; entityAliases[i] = aliases[j]; ++i; } } } @SuppressWarnings({ "unchecked", "rawtypes" }) private void loadSubEntities(Object root) throws HibernateException { try { for (String fieldName : subEntities.keySet()) { Class subclass = (Class) subEntities.get(fieldName).get( FIELDNAME_INDEX); ResultTransformer subclassTransformer = new AliasToBeanNestedResultTransformer( subclass); Object subObject = subclassTransformer.transformTuple( ((List) subEntities.get(fieldName).get(0)) .toArray(), ((List) subEntities.get(fieldName).get(1)) .toArray(new String[0])); Setter setter = accessor.getSetter(resultClass, fieldName); if (listFields.containsKey(fieldName)) { Class collectionClass = listFields.get(fieldName); Collection subObjectList = (Collection) collectionClass .newInstance(); subObjectList.add(subObject); setter.set(root, subObjectList, null); } else { setter.set(root, subObject, null); } } } catch (Exception e) { throw new HibernateException(e); } } private void cleanMaps() { fieldToClass = new HashMap>(); subEntities = new HashMap>(); nestedAliases = new ArrayList(); listFields = new HashMap>(); } } 

我希望它可以帮到你。

————–编辑07/25/15 —————

要对嵌套列表进行分组。

 public List> cleanList( List> resultList) throws DataException { List> entities = new ArrayList>(); Entity current = null; try { for (Entity entity : resultList) { if (entity.getId() == null) { continue; } if (current == null) { current = entity; continue; } if (current.getId().equals(entity.getId())) { append(current, entity); } else { entities.add(current); current = entity; } } if (current != null) { entities.add(current); } cleanSubList(entities); return entities; } catch (Exception e) { throw new DataException(e); } } @SuppressWarnings({ "rawtypes", "unchecked" }) public Set> cleanList( Set> resultList) throws DataException { List listToClean = new LinkedList(); listToClean.addAll(resultList); listToClean = cleanList(listToClean); resultList.clear(); resultList.addAll(listToClean); return resultList; } @SuppressWarnings({ "unchecked", "rawtypes" }) private void append(Entity current, Entity next) throws IllegalArgumentException, IllegalAccessException { Field[] fields = current.getClass().getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(List.class)) { field.setAccessible(true); List valueNext = (List) field.get(next); List valueCurrent = (List) field.get(current); if (valueNext != null) { if (valueCurrent != null) { valueCurrent.addAll(valueNext); field.set(current, valueCurrent); } else { field.set(current, valueNext); } } } else if (field.getType().equals(Set.class)) { field.setAccessible(true); Set valueNext = (Set) field.get(next); Set valueCurrent = (Set) field.get(current); if (valueNext != null) { if (valueCurrent != null) { valueCurrent.addAll(valueNext); field.set(current, valueCurrent); } else { field.set(current, valueNext); } } } } } @SuppressWarnings({ "rawtypes", "unchecked" }) private void cleanSubList(List> listToClean) throws IllegalArgumentException, IllegalAccessException, DataException { for (Entity entity : listToClean) { Field[] fields = entity.getClass().getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(List.class)) { field.setAccessible(true); List valueToClean = (List) field.get(entity); // Throw a thread if (valueToClean != null) { valueToClean = cleanList(valueToClean); field.set(entity, valueToClean); } } else if (field.getType().equals(Set.class)) { field.setAccessible(true); Set valueToClean = (Set) field.get(entity); // Throw a thread if (valueToClean != null) { valueToClean = cleanList(valueToClean); field.set(entity, valueToClean); } } } } } 

为了加快这个过程,我建议在主进程中抛出一个线程。

这是我的实体界面:

 package com.alutiiq.develop.promanagesys.common.entity; import java.io.Serializable; /** * Entity for Hibernate comunications * * @author Miguel Resendiz * * @param  * Primary key type */ public interface Entity extends Serializable { /** * Enable poissibility to write generic queries using primary key * * @return primary key value for entity */ I getId(); void setId(I id); void setId(String id); } 

用法示例:

 criteria.setResultTransformer(new AliasToBeanNestedResultTransformer( entityClass)); List projects = criteria.list(); projects = (List) cleanList(projects);