public void doSecondPass(Map persistentClasses) throws MappingException { // TODO add parameters checkings if (ann == null) return; ResultSetMappingDefinition definition = new ResultSetMappingDefinition(ann.name()); LOG.debugf("Binding result set mapping: %s", definition.getName()); int entityAliasIndex = 0; for (EntityResult entity : ann.entities()) { // TODO parameterize lock mode? List<FieldResult> properties = new ArrayList<FieldResult>(); List<String> propertyNames = new ArrayList<String>(); for (FieldResult field : entity.fields()) { // use an ArrayList cause we might have several columns per root property String name = field.name(); if (name.indexOf('.') == -1) { // regular property properties.add(field); propertyNames.add(name); } else { /** * Reorder properties 1. get the parent property 2. list all the properties following the * expected one in the parent property 3. calculate the lowest index and insert the * property */ PersistentClass pc = mappings.getClass(entity.entityClass().getName()); if (pc == null) { throw new MappingException( "Entity not found " + entity.entityClass().getName() + " in SqlResultsetMapping " + ann.name()); } int dotIndex = name.lastIndexOf('.'); String reducedName = name.substring(0, dotIndex); Iterator parentPropIter = getSubPropertyIterator(pc, reducedName); List followers = getFollowers(parentPropIter, reducedName, name); int index = propertyNames.size(); int followersSize = followers.size(); for (int loop = 0; loop < followersSize; loop++) { String follower = (String) followers.get(loop); int currentIndex = getIndexOfFirstMatchingProperty(propertyNames, follower); index = currentIndex != -1 && currentIndex < index ? currentIndex : index; } propertyNames.add(index, name); properties.add(index, field); } } Set<String> uniqueReturnProperty = new HashSet<String>(); Map<String, ArrayList<String>> propertyResultsTmp = new HashMap<String, ArrayList<String>>(); for (Object property : properties) { final FieldResult propertyresult = (FieldResult) property; final String name = propertyresult.name(); if ("class".equals(name)) { throw new MappingException( "class is not a valid property name to use in a @FieldResult, use @Entity(discriminatorColumn) instead"); } if (uniqueReturnProperty.contains(name)) { throw new MappingException( "duplicate @FieldResult for property " + name + " on @Entity " + entity.entityClass().getName() + " in " + ann.name()); } uniqueReturnProperty.add(name); final String quotingNormalizedColumnName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(propertyresult.column()); String key = StringHelper.root(name); ArrayList<String> intermediateResults = propertyResultsTmp.get(key); if (intermediateResults == null) { intermediateResults = new ArrayList<String>(); propertyResultsTmp.put(key, intermediateResults); } intermediateResults.add(quotingNormalizedColumnName); } Map<String, String[]> propertyResults = new HashMap<String, String[]>(); for (Map.Entry<String, ArrayList<String>> entry : propertyResultsTmp.entrySet()) { propertyResults.put( entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()])); } if (!BinderHelper.isEmptyAnnotationValue(entity.discriminatorColumn())) { final String quotingNormalizedName = mappings .getObjectNameNormalizer() .normalizeIdentifierQuoting(entity.discriminatorColumn()); propertyResults.put("class", new String[] {quotingNormalizedName}); } if (propertyResults.isEmpty()) { propertyResults = java.util.Collections.emptyMap(); } NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn( "alias" + entityAliasIndex++, entity.entityClass().getName(), propertyResults, LockMode.READ); definition.addQueryReturn(result); } for (ColumnResult column : ann.columns()) { definition.addQueryReturn( new NativeSQLQueryScalarReturn( mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(column.name()), null)); } for (ConstructorResult constructorResult : ann.classes()) { List<NativeSQLQueryScalarReturn> columnReturns = new ArrayList<NativeSQLQueryScalarReturn>(); for (ColumnResult columnResult : constructorResult.columns()) { columnReturns.add( new NativeSQLQueryScalarReturn( mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(columnResult.name()), null)); } definition.addQueryReturn( new NativeSQLQueryConstructorReturn(constructorResult.targetClass(), columnReturns)); } if (isDefault) { mappings.addDefaultResultSetMapping(definition); } else { mappings.addResultSetMapping(definition); } }