⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resultsetmappingbinder.java

📁 一个Java持久层类库
💻 JAVA
字号:
//$Id: ResultSetMappingBinder.java 10180 2006-07-28 20:17:01Z epbernard $package org.hibernate.cfg;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Set;import java.util.HashSet;import java.util.Map;import org.dom4j.Element;import org.hibernate.LockMode;import org.hibernate.MappingException;import org.hibernate.engine.query.sql.NativeSQLQueryCollectionReturn;import org.hibernate.engine.ResultSetMappingDefinition;import org.hibernate.engine.query.sql.NativeSQLQueryJoinReturn;import org.hibernate.engine.query.sql.NativeSQLQueryRootReturn;import org.hibernate.engine.query.sql.NativeSQLQueryScalarReturn;import org.hibernate.mapping.Component;import org.hibernate.mapping.PersistentClass;import org.hibernate.mapping.Value;import org.hibernate.mapping.Property;import org.hibernate.mapping.ToOne;import org.hibernate.type.Type;import org.hibernate.type.TypeFactory;import org.hibernate.util.ArrayHelper;import org.hibernate.util.CollectionHelper;import org.hibernate.util.StringHelper;/** * @author Emmanuel Bernard */public abstract class ResultSetMappingBinder {	/**	 * Build a ResultSetMappingDefinition given a containing element for the "return-XXX" elements	 *	 * @param resultSetElem The element containing the return definitions.	 * @param path No clue...	 * @param mappings The current processing state.	 * @return The description of the mappings...	 */	protected static ResultSetMappingDefinition buildResultSetMappingDefinition(Element resultSetElem, String path, Mappings mappings) {		String resultSetName = resultSetElem.attribute( "name" ).getValue();		if ( path != null ) {			resultSetName = path + '.' + resultSetName;		}		ResultSetMappingDefinition definition = new ResultSetMappingDefinition( resultSetName );		int cnt = 0;		Iterator returns = resultSetElem.elementIterator();		while ( returns.hasNext() ) {			cnt++;			Element returnElem = (Element) returns.next();			String name = returnElem.getName();			if ( "return-scalar".equals( name ) ) {				String column = returnElem.attributeValue( "column" );				String typeFromXML = HbmBinder.getTypeFromXML( returnElem );				Type type = null;				if(typeFromXML!=null) {					type = TypeFactory.heuristicType( typeFromXML );					if ( type == null ) {						throw new MappingException( "could not determine type " + type );					}				}				definition.addQueryReturn( new NativeSQLQueryScalarReturn( column, type ) );			}			else if ( "return".equals( name ) ) {				definition.addQueryReturn( bindReturn( returnElem, mappings, cnt ) );			}			else if ( "return-join".equals( name ) ) {				definition.addQueryReturn( bindReturnJoin( returnElem, mappings ) );			}			else if ( "load-collection".equals( name ) ) {				definition.addQueryReturn( bindLoadCollection( returnElem, mappings ) );			}		}		return definition;	}	private static NativeSQLQueryRootReturn bindReturn(Element returnElem, Mappings mappings, int elementCount) {		String alias = returnElem.attributeValue( "alias" );		if( StringHelper.isEmpty(alias)) {			alias = "alias_" + elementCount; // hack/workaround as sqlquery impl depend on having a key.		}		String entityName = HbmBinder.getEntityName(returnElem, mappings);		if(entityName==null) {			throw new MappingException( "<return alias='" + alias + "'> must specify either a class or entity-name");		}		LockMode lockMode = getLockMode( returnElem.attributeValue( "lock-mode" ) );		PersistentClass pc = mappings.getClass( entityName );		java.util.Map propertyResults = bindPropertyResults(alias, returnElem, pc, mappings );		return new NativeSQLQueryRootReturn(				alias,				entityName,				propertyResults,				lockMode			);	}	private static NativeSQLQueryJoinReturn bindReturnJoin(Element returnElem, Mappings mappings) {		String alias = returnElem.attributeValue( "alias" );		String roleAttribute = returnElem.attributeValue( "property" );		LockMode lockMode = getLockMode( returnElem.attributeValue( "lock-mode" ) );		int dot = roleAttribute.lastIndexOf( '.' );		if ( dot == -1 ) {			throw new MappingException(					"Role attribute for sql query return [alias=" + alias +					"] not formatted correctly {owningAlias.propertyName}"				);		}		String roleOwnerAlias = roleAttribute.substring( 0, dot );		String roleProperty = roleAttribute.substring( dot + 1 );		//FIXME: get the PersistentClass		java.util.Map propertyResults = bindPropertyResults(alias, returnElem, null, mappings );		return new NativeSQLQueryJoinReturn(				alias,				roleOwnerAlias,				roleProperty,				propertyResults, // TODO: bindpropertyresults(alias, returnElem)				lockMode			);	}	private static NativeSQLQueryCollectionReturn bindLoadCollection(Element returnElem, Mappings mappings) {		String alias = returnElem.attributeValue( "alias" );		String collectionAttribute = returnElem.attributeValue( "role" );		LockMode lockMode = getLockMode( returnElem.attributeValue( "lock-mode" ) );		int dot = collectionAttribute.lastIndexOf( '.' );		if ( dot == -1 ) {			throw new MappingException(					"Collection attribute for sql query return [alias=" + alias +					"] not formatted correctly {OwnerClassName.propertyName}"				);		}		String ownerClassName = HbmBinder.getClassName( collectionAttribute.substring( 0, dot ), mappings );		String ownerPropertyName = collectionAttribute.substring( dot + 1 );		//FIXME: get the PersistentClass		java.util.Map propertyResults = bindPropertyResults(alias, returnElem, null, mappings );		return new NativeSQLQueryCollectionReturn(				alias,				ownerClassName,				ownerPropertyName,				propertyResults,				lockMode			);	}	private static java.util.Map bindPropertyResults(			String alias, Element returnElement, PersistentClass pc, Mappings mappings	) {		HashMap propertyresults = new HashMap(); // maybe a concrete SQLpropertyresult type, but Map is exactly what is required at the moment		Element discriminatorResult = returnElement.element("return-discriminator");		if(discriminatorResult!=null) {			ArrayList resultColumns = getResultColumns(discriminatorResult);			propertyresults.put("class", ArrayHelper.toStringArray(resultColumns) );		}		Iterator iterator = returnElement.elementIterator("return-property");		List properties = new ArrayList();		List propertyNames = new ArrayList();		while ( iterator.hasNext() ) {			Element propertyresult = (Element) iterator.next();			String name = propertyresult.attributeValue("name");			if ( pc == null || name.indexOf( '.') == -1) { //if dotted and not load-collection nor return-join				//regular property				properties.add(propertyresult);				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				 */				if (pc == null)					throw new MappingException("dotted notation in <return-join> or <load_collection> not yet supported");				int dotIndex = name.lastIndexOf( '.' );				String reducedName = name.substring( 0, dotIndex );				Value value = pc.getRecursiveProperty( reducedName ).getValue();				Iterator parentPropIter;				if ( value instanceof Component ) {					Component comp = (Component) value;					parentPropIter = comp.getPropertyIterator();				}				else if ( value instanceof ToOne ) {					ToOne toOne = (ToOne) value;					PersistentClass referencedPc = mappings.getClass( toOne.getReferencedEntityName() );					if ( toOne.getReferencedPropertyName() != null ) {						try {							parentPropIter = ( (Component) referencedPc.getRecursiveProperty( toOne.getReferencedPropertyName() ).getValue() ).getPropertyIterator();						} catch (ClassCastException e) {							throw new MappingException("dotted notation reference neither a component nor a many/one to one", e);						}					}					else {						try {							if ( referencedPc.getIdentifierMapper() == null ) {								parentPropIter = ( (Component) referencedPc.getIdentifierProperty().getValue() ).getPropertyIterator();							}							else {								parentPropIter = referencedPc.getIdentifierMapper().getPropertyIterator();							}						}						catch (ClassCastException e) {							throw new MappingException("dotted notation reference neither a component nor a many/one to one", e);						}					}				}				else {					throw new MappingException("dotted notation reference neither a component nor a many/one to one");				}				boolean hasFollowers = false;				List followers = new ArrayList();				while ( parentPropIter.hasNext() ) {					String currentPropertyName = ( (Property) parentPropIter.next() ).getName();					String currentName = reducedName + '.' + currentPropertyName;					if (hasFollowers) {						followers.add( currentName );					}					if ( name.equals( currentName ) ) hasFollowers = true;				}				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, propertyresult);			}		}		Set uniqueReturnProperty = new HashSet();		iterator = properties.iterator();		while ( iterator.hasNext() ) {			Element propertyresult = (Element) iterator.next();			String name = propertyresult.attributeValue("name");			if ( "class".equals(name) ) {				throw new MappingException(						"class is not a valid property name to use in a <return-property>, use <return-discriminator> instead"					);			}			//TODO: validate existing of property with the chosen name. (secondpass )			ArrayList allResultColumns = getResultColumns(propertyresult);			if ( allResultColumns.isEmpty() ) {				throw new MappingException(						"return-property for alias " + alias +						" must specify at least one column or return-column name"					);			}			if ( uniqueReturnProperty.contains( name ) ) {				throw new MappingException(						"duplicate return-property for property " + name +						" on alias " + alias					);			}			uniqueReturnProperty.add(name);			// the issue here is that for <return-join/> representing an entity collection,			// the collection element values (the property values of the associated entity)			// are represented as 'element.{propertyname}'.  Thus the StringHelper.root()			// here puts everything under 'element' (which additionally has significant			// meaning).  Probably what we need to do is to something like this instead:			//      String root = StringHelper.root( name );			//      String key = root; // by default			//      if ( !root.equals( name ) ) {			//	        // we had a dot			//          if ( !root.equals( alias ) {			//              // the root does not apply to the specific alias			//              if ( "elements".equals( root ) {			//                  // we specifically have a <return-join/> representing an entity collection			//                  // and this <return-property/> is one of that entity's properties			//                  key = name;			//              }			//          }			//      }			// but I am not clear enough on the intended purpose of this code block, especially			// in relation to the "Reorder properties" code block above... //			String key = StringHelper.root( name );			String key = name;			ArrayList intermediateResults = (ArrayList) propertyresults.get( key );			if (intermediateResults == null) {				propertyresults.put( key, allResultColumns );			}			else {				intermediateResults.addAll( allResultColumns );			}		}		Iterator entries = propertyresults.entrySet().iterator();		while ( entries.hasNext() ) {			Map.Entry entry = (Map.Entry) entries.next();			if (entry.getValue() instanceof ArrayList) {				ArrayList list = (ArrayList) entry.getValue();				entry.setValue( list.toArray( new String[ list.size() ] ) );			}		}		return propertyresults.isEmpty() ? CollectionHelper.EMPTY_MAP : propertyresults;	}	private static int getIndexOfFirstMatchingProperty(List propertyNames, String follower) {		int propertySize = propertyNames.size();		for (int propIndex = 0 ; propIndex < propertySize ; propIndex++) {			if ( ( (String) propertyNames.get(propIndex) ).startsWith( follower ) ) {				return propIndex;			}		}		return -1;	}	private static ArrayList getResultColumns(Element propertyresult) {		String column = unquote(propertyresult.attributeValue("column"));		ArrayList allResultColumns = new ArrayList();		if(column!=null) allResultColumns.add(column);		Iterator resultColumns = propertyresult.elementIterator("return-column");		while ( resultColumns.hasNext() ) {			Element element = (Element) resultColumns.next();			allResultColumns.add( unquote(element.attributeValue("name")) );		}		return allResultColumns;	}	private static String unquote(String name) {		if (name!=null && name.charAt(0)=='`') {			name=name.substring( 1, name.length()-1 );		}		return name;	}	private static LockMode getLockMode(String lockMode) {		if ( lockMode == null || "read".equals( lockMode ) ) {			return LockMode.READ;		}		else if ( "none".equals( lockMode ) ) {			return LockMode.NONE;		}		else if ( "upgrade".equals( lockMode ) ) {			return LockMode.UPGRADE;		}		else if ( "upgrade-nowait".equals( lockMode ) ) {			return LockMode.UPGRADE_NOWAIT;		}		else if ( "write".equals( lockMode ) ) {			return LockMode.WRITE;		}		else if ( "force".equals( lockMode ) ) {			return LockMode.FORCE;		}		else {			throw new MappingException( "unknown lockmode" );		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -