[hibernate-commits] Hibernate SVN: r16653 - in core/branches/Branch_3_2/src/org/hibernate: loader and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Jun 1 16:36:36 EDT 2009


Author: steve.ebersole at jboss.com
Date: 2009-06-01 16:36:35 -0400 (Mon, 01 Jun 2009)
New Revision: 16653

Modified:
   core/branches/Branch_3_2/src/org/hibernate/cache/QueryKey.java
   core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java
   core/branches/Branch_3_2/src/org/hibernate/util/CollectionHelper.java
Log:
HHH-3383 - QueryKey is storing references to entities instead of identifiers


Modified: core/branches/Branch_3_2/src/org/hibernate/cache/QueryKey.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cache/QueryKey.java	2009-06-01 18:54:44 UTC (rev 16652)
+++ core/branches/Branch_3_2/src/org/hibernate/cache/QueryKey.java	2009-06-01 20:36:35 UTC (rev 16653)
@@ -1,19 +1,47 @@
-//$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.cache;
 
 import java.io.Serializable;
+import java.io.IOException;
 import java.util.Map;
 import java.util.Set;
+import java.util.Iterator;
 
 import org.hibernate.EntityMode;
 import org.hibernate.engine.QueryParameters;
 import org.hibernate.engine.RowSelection;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.TypedValue;
 import org.hibernate.transform.ResultTransformer;
 import org.hibernate.type.Type;
 import org.hibernate.util.EqualsHelper;
+import org.hibernate.util.CollectionHelper;
 
 /**
  * A key that identifies a particular query with bound parameter values
+ *
  * @author Gavin King
  */
 public class QueryKey implements Serializable {
@@ -25,17 +53,51 @@
 	private final Map namedParameters;
 	private final EntityMode entityMode;
 	private final Set filters;
-	private final int hashCode;
-	
+
 	// the user provided resulttransformer, not the one used with "select new". Here to avoid mangling transformed/non-transformed results.
 	private final ResultTransformer customTransformer;
-	
-	public QueryKey(String queryString, QueryParameters queryParameters, Set filters, EntityMode entityMode) {
-		this.sqlQueryString = queryString;
-		this.types = queryParameters.getPositionalParameterTypes();
-		this.values = queryParameters.getPositionalParameterValues();
-		RowSelection selection = queryParameters.getRowSelection();
-		if (selection!=null) {
+
+	/**
+	 * For performance reasons, the hashCode is cached; however, it is marked transient so that it can be
+	 * recalculated as part of the serialization process which allows distributed query caches to work properly.
+	 */
+	private transient int hashCode;
+
+	public static QueryKey generateQueryKey(
+			String queryString,
+			QueryParameters queryParameters,
+			Set filters,
+			SessionImplementor session) {
+		// disassemble positional parameters
+		final int positionalParameterCount = queryParameters.getPositionalParameterTypes().length;
+		final Type[] types = new Type[positionalParameterCount];
+		final Object[] values = new Object[positionalParameterCount];
+		for ( int i = 0; i < positionalParameterCount; i++ ) {
+			types[i] = queryParameters.getPositionalParameterTypes()[i];
+			values[i] = types[i].disassemble( queryParameters.getPositionalParameterValues()[i], session, null );
+		}
+
+		// disassemble named parameters
+		Map namedParameters = CollectionHelper.mapOfSize( queryParameters.getNamedParameters().size() );
+		Iterator itr = queryParameters.getNamedParameters().entrySet().iterator();
+		while ( itr.hasNext() ) {
+			final Map.Entry namedParameterEntry = ( Map.Entry ) itr.next();
+			final TypedValue original = ( TypedValue ) namedParameterEntry.getValue();
+			namedParameters.put(
+					namedParameterEntry.getKey(),
+					new TypedValue(
+							original.getType(),
+							original.getType().disassemble( original.getValue(), session, null ),
+							session.getEntityMode()
+					)
+			);
+		}
+
+		// decode row selection...
+		final RowSelection selection = queryParameters.getRowSelection();
+		final Integer firstRow;
+		final Integer maxRows;
+		if ( selection != null ) {
 			firstRow = selection.getFirstRow();
 			maxRows = selection.getMaxRows();
 		}
@@ -43,40 +105,48 @@
 			firstRow = null;
 			maxRows = null;
 		}
-		this.namedParameters = queryParameters.getNamedParameters();
+
+		return new QueryKey(
+				queryString,
+				types,
+				values,
+				namedParameters,
+				firstRow,
+				maxRows,
+				filters,
+				session.getEntityMode(),
+				queryParameters.getResultTransformer()
+		);
+	}
+
+	/*package*/ QueryKey(
+			String sqlQueryString,
+			Type[] types,
+			Object[] values,
+			Map namedParameters,
+			Integer firstRow,
+			Integer maxRows,
+			Set filters,
+			EntityMode entityMode,
+			ResultTransformer customTransformer) {
+		this.sqlQueryString = sqlQueryString;
+		this.types = types;
+		this.values = values;
+		this.namedParameters = namedParameters;
+		this.firstRow = firstRow;
+		this.maxRows = maxRows;
 		this.entityMode = entityMode;
 		this.filters = filters;
-		this.customTransformer = queryParameters.getResultTransformer();
-		this.hashCode = getHashCode();
+		this.customTransformer = customTransformer;
+		this.hashCode = generateHashCode();
 	}
-	
-	public boolean equals(Object other) {
-		if ( !( other instanceof QueryKey ) ) return false;
-		QueryKey that = (QueryKey) other;
-		if ( !sqlQueryString.equals(that.sqlQueryString) ) return false;
-		if ( !EqualsHelper.equals(firstRow, that.firstRow) || !EqualsHelper.equals(maxRows, that.maxRows) ) return false;
-		if ( !EqualsHelper.equals(customTransformer, that.customTransformer) ) return false;
-		if (types==null) {
-			if (that.types!=null) return false;
-		}
-		else {
-			if (that.types==null) return false;
-			if ( types.length!=that.types.length ) return false;
-			for ( int i=0; i<types.length; i++ ) {
-				if ( types[i].getReturnedClass() != that.types[i].getReturnedClass() ) return false;
-				if ( !types[i].isEqual( values[i], that.values[i], entityMode ) ) return false;
-			}
-		}
-		if ( !EqualsHelper.equals(filters, that.filters) ) return false;
-		if ( !EqualsHelper.equals(namedParameters, that.namedParameters) ) return false;
-		return true;
+
+	private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+		in.defaultReadObject();
+		this.hashCode = generateHashCode();
 	}
-	
-	public int hashCode() {
-		return hashCode;
-	}
-	
-	private int getHashCode() {
+
+	private int generateHashCode() {
 		int result = 13;
 		result = 37 * result + ( firstRow==null ? 0 : firstRow.hashCode() );
 		result = 37 * result + ( maxRows==null ? 0 : maxRows.hashCode() );
@@ -90,29 +160,79 @@
 		return result;
 	}
 
+	public boolean equals(Object other) {
+		if ( !( other instanceof QueryKey ) ) {
+			return false;
+		}
+		QueryKey that = ( QueryKey ) other;
+		if ( !sqlQueryString.equals( that.sqlQueryString ) ) {
+			return false;
+		}
+		if ( !EqualsHelper.equals( firstRow, that.firstRow ) || !EqualsHelper.equals( maxRows, that.maxRows ) ) {
+			return false;
+		}
+		if ( !EqualsHelper.equals( customTransformer, that.customTransformer ) ) {
+			return false;
+		}
+		if ( types == null ) {
+			if ( that.types != null ) {
+				return false;
+			}
+		}
+		else {
+			if ( that.types == null ) {
+				return false;
+			}
+			if ( types.length != that.types.length ) {
+				return false;
+			}
+			for ( int i = 0; i < types.length; i++ ) {
+				if ( types[i].getReturnedClass() != that.types[i].getReturnedClass() ) {
+					return false;
+				}
+				if ( !types[i].isEqual( values[i], that.values[i], entityMode ) ) {
+					return false;
+				}
+			}
+		}
+
+		return EqualsHelper.equals( filters, that.filters )
+				&& EqualsHelper.equals( namedParameters, that.namedParameters );
+	}
+
+	public int hashCode() {
+		return hashCode;
+	}
+
 	public String toString() {
 		StringBuffer buf = new StringBuffer()
-			.append("sql: ")
-			.append(sqlQueryString);
-		if (values!=null) {
-			buf.append("; parameters: ");
-			for (int i=0; i<values.length; i++) {
+				.append( "sql: " )
+				.append( sqlQueryString );
+		if ( values != null ) {
+			buf.append( "; parameters: " );
+			for ( int i = 0; i < values.length; i++ ) {
 				buf.append( values[i] )
-					.append(", ");
+						.append( ", " );
 			}
 		}
-		if (namedParameters!=null) {
-			buf.append("; named parameters: ")
-				.append(namedParameters);
+		if ( namedParameters != null ) {
+			buf.append( "; named parameters: " )
+					.append( namedParameters );
 		}
-		if (filters!=null) {
-			buf.append("; filters: ")
-				.append(filters);
+		if ( filters != null ) {
+			buf.append( "; filters: " )
+					.append( filters );
 		}
-		if (firstRow!=null) buf.append("; first row: ").append(firstRow);
-		if (maxRows!=null) buf.append("; max rows: ").append(maxRows);
-		if (customTransformer!=null) buf.append("; transformer: ").append(customTransformer);
+		if ( firstRow != null ) {
+			buf.append( "; first row: " ).append( firstRow );
+		}
+		if ( maxRows != null ) {
+			buf.append( "; max rows: " ).append( maxRows );
+		}
+		if ( customTransformer != null ) {
+			buf.append( "; transformer: " ).append( customTransformer );
+		}
 		return buf.toString();
 	}
-	
+
 }

Modified: core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java	2009-06-01 18:54:44 UTC (rev 16652)
+++ core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java	2009-06-01 20:36:35 UTC (rev 16653)
@@ -2117,15 +2117,15 @@
 		QueryCache queryCache = factory.getQueryCache( queryParameters.getCacheRegion() );
 		
 		Set filterKeys = FilterKey.createFilterKeys( 
-				session.getEnabledFilters(), 
+				session.getEnabledFilters(),
 				session.getEntityMode() 
-			);
-		QueryKey key = new QueryKey( 
+		);
+		QueryKey key = QueryKey.generateQueryKey(
 				getSQLString(), 
 				queryParameters, 
 				filterKeys, 
-				session.getEntityMode() 
-			);
+				session
+		);
 		
 		List result = getResultFromQueryCache( 
 				session, 
@@ -2134,7 +2134,7 @@
 				resultTypes, 
 				queryCache, 
 				key 
-			);
+		);
 
 		if ( result == null ) {
 			result = doList( session, queryParameters );
@@ -2146,7 +2146,7 @@
 					queryCache, 
 					key, 
 					result 
-				);
+			);
 		}
 
 		return getResultList( result, queryParameters.getResultTransformer() );

Modified: core/branches/Branch_3_2/src/org/hibernate/util/CollectionHelper.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/util/CollectionHelper.java	2009-06-01 18:54:44 UTC (rev 16652)
+++ core/branches/Branch_3_2/src/org/hibernate/util/CollectionHelper.java	2009-06-01 20:36:35 UTC (rev 16653)
@@ -1,4 +1,26 @@
-//$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.util;
 
 import java.util.ArrayList;
@@ -9,14 +31,30 @@
 import java.util.Map;
 
 /**
+ * Various help for handling collections.
+ *
  * @author Gavin King
+ * @author Steve Ebersole
  */
 public final class CollectionHelper {
 
 	public static final List EMPTY_LIST = Collections.unmodifiableList( new ArrayList(0) );
 	public static final Collection EMPTY_COLLECTION = Collections.unmodifiableCollection( new ArrayList(0) );
 	public static final Map EMPTY_MAP = Collections.unmodifiableMap( new HashMap(0) );
-	
-	private CollectionHelper() {}
 
+	private CollectionHelper() {
+	}
+
+	/**
+	 * Build a properly sized map, especially handling load size and load factor to prevent immediate resizing.
+	 * <p/>
+	 * Especially helpful for copy map contents.
+	 *
+	 * @param size The size to make the map.
+	 * @return The sized map.
+	 */
+	public static Map mapOfSize(int size) {
+		final int currentSize = (int) (size / 0.75f);
+		return new HashMap( Math.max( currentSize+ 1, 16), 0.75f );
+	}
 }




More information about the hibernate-commits mailing list