Java Mailing List Archive

http://www.gg3721.com/

Home » Hibernate Commits List »

[hibernate-commits] Hibernate SVN: r15175 - in
 core/branches/Branch_3_3:
 core/src/main/java/org/hibernate/criterion and 5 other directories.

hibernate-commits

2008-09-10


Author LoginPost Reply
Author: steve.ebersole@(protected)
Date: 2008-09-10 13:03:42 -0400 (Wed, 10 Sep 2008)
New Revision: 15175

Added:
 core/branches/Branch_3_3/core/src/test/java/org/hibernate/cache/
 core/branches/Branch_3_3/core/src/test/java/org/hibernate/cache/QueryKeyTest.java
Modified:
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/cache/QueryKey.java
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/CriteriaSpecification.java
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/BasicTransformerAdapter.java
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java
 core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java
 core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java
 core/branches/Branch_3_3/testsuite/src/test/resources/log4j.properties
Log:
HHH-3392 : query cache cluster replication with ResultTransformers

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/cache/QueryKey.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/cache/QueryKey.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/cache/QueryKey.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
package org.hibernate.cache;

import java.io.Serializable;
+import java.io.IOException;
import java.util.Map;
import java.util.Set;

@@(protected) @@
 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;
+
+  /**
+   * 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 QueryKey(String queryString, QueryParameters queryParameters, Set filters, EntityMode entityMode) {
   this.sqlQueryString = queryString;
@@(protected) @@
   this.entityMode = entityMode;
   this.filters = filters;
   this.customTransformer = queryParameters.getResultTransformer();
-    this.hashCode = getHashCode();
+    this.hashCode = generateHashCode();
 }
+
+  private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+    in.defaultReadObject();
+    this.hashCode = generateHashCode();
+  }
+
+  private int generateHashCode() {
+    int result = 13;
+    result = 37 * result + ( firstRow==null ? 0 : firstRow.hashCode() );
+    result = 37 * result + ( maxRows==null ? 0 : maxRows.hashCode() );
+    for ( int i=0; i<values.length; i++ ) {
+      result = 37 * result + ( values[i]==null ? 0 : types[i].getHashCode( values[i], entityMode ) );
+    }
+    result = 37 * result + ( namedParameters==null ? 0 : namedParameters.hashCode() );
+    result = 37 * result + ( filters==null ? 0 : filters.hashCode() );
+    result = 37 * result + ( customTransformer==null ? 0 : customTransformer.hashCode() );
+    result = 37 * result + sqlQueryString.hashCode();
+    return result;
+  }
+
+  public int hashCode() {
+    return hashCode;
+  }
 
 public boolean equals(Object other) {
   if (!(other instanceof QueryKey)) return false;
@@(protected) @@
   if ( !EqualsHelper.equals(namedParameters, that.namedParameters) ) return false;
   return true;
 }
-  
-  public int hashCode() {
-    return hashCode;
-  }
-  
-  private int getHashCode() {
-    int result = 13;
-    result = 37 * result + ( firstRow==null ? 0 : firstRow.hashCode() );
-    result = 37 * result + ( maxRows==null ? 0 : maxRows.hashCode() );
-    for ( int i=0; i<values.length; i++ ) {
-      result = 37 * result + ( values[i]==null ? 0 : types[i].getHashCode( values[i], entityMode ) );
-    }
-    result = 37 * result + ( namedParameters==null ? 0 : namedParameters.hashCode() );
-    result = 37 * result + ( filters==null ? 0 : filters.hashCode() );
-    result = 37 * result + ( customTransformer==null ? 0 : customTransformer.hashCode() );
-    result = 37 * result + sqlQueryString.hashCode();
-    return result;
-  }

 public String toString() {
   StringBuffer buf = new StringBuffer()

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/CriteriaSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/CriteriaSpecification.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/CriteriaSpecification.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
 /**
  * Each row of results is a <tt>Map</tt> from alias to entity instance
  */
-  public static final ResultTransformer ALIAS_TO_ENTITY_MAP = new AliasToEntityMapResultTransformer();
+  public static final ResultTransformer ALIAS_TO_ENTITY_MAP = AliasToEntityMapResultTransformer.INSTANCE;

 /**
  * Each row of results is an instance of the root entity
  */
-  public static final ResultTransformer ROOT_ENTITY = new RootEntityResultTransformer();
+  public static final ResultTransformer ROOT_ENTITY = RootEntityResultTransformer.INSTANCE;

 /**
  * Each row of results is a distinct instance of the root entity
  */
-  public static final ResultTransformer DISTINCT_ROOT_ENTITY = new DistinctRootEntityResultTransformer();
+  public static final ResultTransformer DISTINCT_ROOT_ENTITY = DistinctRootEntityResultTransformer.INSTANCE;

 /**
  * This result transformer is selected implicitly by calling <tt>setProjection()</tt>
  */
-  public static final ResultTransformer PROJECTION = new PassThroughResultTransformer();
+  public static final ResultTransformer PROJECTION = PassThroughResultTransformer.INSTANCE;

 /**
  * Specifies joining to an entity based on an inner join.

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
import java.io.Serializable;

/**
- * {@(protected)",
- * made up of each aliased value where the alias is the map key.
+ * {@(protected)
+ * where the alias is the map key.
* <p/>
- * Since this transformer is stateless, all instances would be considered equal.
- * So for optimization purposes we limit it to a single, singleton {@(protected)}.
+ * Since this transformer is stateless, all instances would be considered equal. So for optimization purposes
+ * we limit it to a single, singleton {@(protected)
+ * on {@(protected)}).
*
* @author Gavin King
* @author Steve Ebersole
@@(protected) @@

 /**
  * Instantiate AliasToEntityMapResultTransformer.
+   * <p/>
+   * todo : make private, see deprecation...
  *
-   * @deprecated Use the {@(protected).
+   * @deprecated Use the {@(protected)).
  */
 public AliasToEntityMapResultTransformer() {
-    // todo : make private
 }

+  /**
+   * {@(protected)}
+   */
 public Object transformTuple(Object[] tuple, String[] aliases) {
   Map result = new HashMap(tuple.length);
   for ( int i=0; i<tuple.length; i++ ) {
@@(protected) @@
  * All AliasToEntityMapResultTransformer are considered equal
  *
  * @param other The other instance to check for equality
-   * @return True if (non-null) other is a instance of
-   * AliasToEntityMapResultTransformer.
+   * @return True if (non-null) other is a instance of AliasToEntityMapResultTransformer.
  */
 public boolean equals(Object other) {
   // todo : we can remove this once the deprecated ctor can be made private...
@@(protected) @@
 /**
  * All AliasToEntityMapResultTransformer are considered equal
  *
-   * @return We simply return the hashCode of the
-   * AliasToEntityMapResultTransformer class name string.
+   * @return We simply return the hashCode of the AliasToEntityMapResultTransformer class name string.
  */
 public int hashCode() {
   // todo : we can remove this once the deprecated ctor can be made private...

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/BasicTransformerAdapter.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/BasicTransformerAdapter.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/BasicTransformerAdapter.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
* @author Steve Ebersole
*/
public abstract class BasicTransformerAdapter implements ResultTransformer {
+  /**
+   * {@(protected)}
+   */
 public Object transformTuple(Object[] tuple, String[] aliases) {
   return tuple;
 }

+  /**
+   * {@(protected)}
+   */
 public List transformList(List list) {
   return list;
 }

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
import java.io.Serializable;

/**
- * Much like {@(protected)
- * the entity in the final result.
+ * Much like {@(protected).
* <p/>
- * Since this transformer is stateless, all instances would be considered equal.
- * So for optimization purposes we limit it to a single, singleton {@(protected)}.
+ * Since this transformer is stateless, all instances would be considered equal. So for optimization purposes
+ * we limit it to a single, singleton {@(protected)
+ * on {@(protected)}).
*
* @author Gavin King
* @author Steve Ebersole
@@(protected) @@

 /**
  * Instantiate a DistinctRootEntityResultTransformer.
+   * <p/>
+   * todo : make private, see deprecation notice
  *
-   * @deprecated Use the {@(protected).
+   * @deprecated Use the {@(protected)).
  */
 public DistinctRootEntityResultTransformer() {
 }
@@(protected) @@
   return INSTANCE;
 }

-  public boolean equals(Object obj) {
+
+  // all DistinctRootEntityResultTransformer are considered equal ~~~~~~~~~~~
+
+  public int hashCode() {
   // todo : we can remove this once the deprecated ctor can be made private...
-    return DistinctRootEntityResultTransformer.class.isInstance( obj );
+    return DistinctRootEntityResultTransformer.class.getName().hashCode();
 }
+
+  public boolean equals(Object other) {
+    // todo : we can remove this once the deprecated ctor can be made private...
+    return other != null && DistinctRootEntityResultTransformer.class.isInstance( other );
+  }
}

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
 /**
  * Instamtiate a PassThroughResultTransformer.
  *
-   * @deprecated Use the {@(protected).
+   * @deprecated Use the {@(protected)).
  */
 public PassThroughResultTransformer() {
 }
@@(protected) @@
   return INSTANCE;
 }

-  public boolean equals(Object obj) {
+  public int hashCode() {
   // todo : we can remove this once the deprecated ctor can be made private...
-    return PassThroughResultTransformer.class.isInstance( obj );
+    return PassThroughResultTransformer.class.getName().hashCode();
 }

+  public boolean equals(Object other) {
+    // todo : we can remove this once the deprecated ctor can be made private...
+    return other != null && PassThroughResultTransformer.class.isInstance( other );
+  }
+
}

Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
 /**
  * Instantiate RootEntityResultTransformer.
  *
-   * @deprecated Use the {@(protected).
+   * @deprecated Use the {@(protected)).
  */
 public RootEntityResultTransformer() {
 }
@@(protected) @@
   return INSTANCE;
 }

-  public boolean equals(Object obj) {
+  public int hashCode() {
   // todo : we can remove this once the deprecated ctor can be made private...
-    return RootEntityResultTransformer.class.isInstance( obj );
+    return RootEntityResultTransformer.class.getName().hashCode();
 }
+
+  public boolean equals(Object other) {
+    // todo : we can remove this once the deprecated ctor can be made private...
+    return other != null && RootEntityResultTransformer.class.isInstance( other );
+  }
}

Added: core/branches/Branch_3_3/core/src/test/java/org/hibernate/cache/QueryKeyTest.java
===================================================================
--- core/branches/Branch_3_3/core/src/test/java/org/hibernate/cache/QueryKeyTest.java                  (rev 0)
+++ core/branches/Branch_3_3/core/src/test/java/org/hibernate/cache/QueryKeyTest.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
+/*
+ * 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.util.Collections;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+import org.hibernate.engine.QueryParameters;
+import org.hibernate.EntityMode;
+import org.hibernate.transform.RootEntityResultTransformer;
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.transform.DistinctRootEntityResultTransformer;
+import org.hibernate.transform.AliasToEntityMapResultTransformer;
+import org.hibernate.transform.PassThroughResultTransformer;
+import org.hibernate.transform.DistinctResultTransformer;
+import org.hibernate.util.SerializationHelper;
+import org.hibernate.util.ArrayHelper;
+
+/**
+ * Tests relating to {@(protected).
+ *
+ * @author Steve Ebersole
+ */
+public class QueryKeyTest extends TestCase {
+  private static final String QUERY_STRING = "the query string";
+
+  public void testSerializedEquality() {
+    doTest( buildBasicKey( new QueryParameters() ) );
+  }
+
+  public void testSerializedEqualityWithResultTransformer() {
+    doTest( buildBasicKey( buildQueryParameters( RootEntityResultTransformer.INSTANCE ) ) );
+    doTest( buildBasicKey( buildQueryParameters( DistinctRootEntityResultTransformer.INSTANCE ) ) );
+    doTest( buildBasicKey( buildQueryParameters( DistinctResultTransformer.INSTANCE ) ) );
+    doTest( buildBasicKey( buildQueryParameters( AliasToEntityMapResultTransformer.INSTANCE ) ) );
+    doTest( buildBasicKey( buildQueryParameters( PassThroughResultTransformer.INSTANCE ) ) );
+  }
+
+  private QueryParameters buildQueryParameters(ResultTransformer resultTransformer) {
+    return new QueryParameters(
+        ArrayHelper.EMPTY_TYPE_ARRAY,    // param types
+        ArrayHelper.EMPTY_OBJECT_ARRAY,    // param values
+        Collections.EMPTY_MAP,        // lock modes
+        null,                // row selection
+        false,                // cacheable?
+        "",                  // cache region
+        "",                // SQL comment
+        false,                // is natural key lookup?
+        resultTransformer          // the result transformer, duh! ;)
+    );
+  }
+
+  private QueryKey buildBasicKey(QueryParameters queryParameters) {
+    return new QueryKey( QUERY_STRING, queryParameters, Collections.EMPTY_SET, EntityMode.POJO );
+  }
+
+  private void doTest(QueryKey key) {
+    HashMap map = new HashMap();
+
+    map.put( key, "" );
+    assert map.size() == 1 : "really messed up";
+
+    Object old = map.put( key, "value" );
+    assert old != null && map.size() == 1 : "apparent QueryKey equals/hashCode issue";
+
+    // finally, lets serialize it and see what happens
+    QueryKey key2 = ( QueryKey ) SerializationHelper.clone( key );
+    assert key != key2 : "deep copy issue";
+    old = map.put( key2, "new value" );
+    assert old != null && map.size() == 1 : "deserialization did not set hashCode or equals properly";
+  }
+}

Modified: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.HashMap;

import junit.framework.Test;

@@(protected) @@
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import org.hibernate.transform.Transformers;
-import org.hibernate.transform.AliasToEntityMapResultTransformer;
+import org.hibernate.transform.BasicTransformerAdapter;

/**
* Tests of various features of native SQL queries.
@@(protected) @@
          "   left outer join EMPLOYMENT emp on org.ORGID = emp.EMPLOYER, ORGANIZATION org2" )
   .addEntity("org", Organization.class)
   .addJoin("emp", "org.employments")
-    .setResultTransformer(new DistinctRootEntityResultTransformer())
+    .setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
   .list();
   assertEquals( l.size(), 2 );

@@(protected) @@
   }
 }

-  private static class UpperCasedAliasToEntityMapResultTransformer extends AliasToEntityMapResultTransformer {
+  private static class UpperCasedAliasToEntityMapResultTransformer extends BasicTransformerAdapter implements Serializable {
   public Object transformTuple(Object[] tuple, String[] aliases) {
-      String[] ucAliases = new String[aliases.length];
-      for ( int i = 0; i < aliases.length; i++ ) {
-        ucAliases[i] = aliases[i].toUpperCase();
+      Map result = new HashMap( tuple.length );
+      for ( int i = 0; i < tuple.length; i++ ) {
+        String alias = aliases[i];
+        if ( alias != null ) {
+          result.put( alias.toUpperCase(), tuple[i] );
+        }
     }
-      return super.transformTuple( tuple, ucAliases );
+      return result;
   }
 }
}

Modified: core/branches/Branch_3_3/testsuite/src/test/resources/log4j.properties
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/resources/log4j.properties  2008-09-10 17:02:45 UTC (rev 15174)
+++ core/branches/Branch_3_3/testsuite/src/test/resources/log4j.properties  2008-09-10 17:03:42 UTC (rev 15175)
@@(protected) @@

log4j.rootLogger=info, stdout

-log4j.logger.org.hibernate.test=info
\ No newline at end of file
+log4j.logger.org.hibernate.test=info
+log4j.logger.org.hibernate.tool.hbm2ddl=debug
\ No newline at end of file

_______________________________________________
hibernate-commits mailing list
hibernate-commits@(protected)
https://lists.jboss.org/mailman/listinfo/hibernate-commits
©2008 gg3721.com - Jax Systems, LLC, U.S.A.