Bug 75 : autoFetch builds different queryHashCode between runs
Priority 
High
Reported Version 
 
Logged By 
imario
Status 
Fixed
Fixed Version 
1.1.0
Assigned To 
 
Product 
Ebean - core
Duplicate Of 
 
Created 
22/02/2009
Updated 
22/02/2009
Type 
Bug
 
Attachments 
No attachments

autofetch builds different queryHashCodes between successive runs of your application.

1) avaje builds hash-codes using xyz.class.hashCode() which does NOT results into the same hashCode() between application starts. It seems the hashCode of a class is stable only within the same instance of a JVM.

I propose to fix this using xyz.class.getName().hashCode()

2) In SimpleExpression there is an enum which behaves like a class, thush hashCode() can't be called there too. proposal: enum.name().hashCode()


Here is a patch which solves that:

Index: ../ebean/src/com/avaje/ebean/expression/IdExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/IdExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/IdExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -42,7 +42,7 @@
public int queryPlanHash() {
// this number is unique for a given bean type
// which is all that is required
- return IdExpression.class.hashCode();
+ return IdExpression.class.getName().hashCode();
}

public int queryBindHash() {
Index: ../ebean/src/com/avaje/ebean/server/transaction/TableModInfo.java
===================================================================
--- ../ebean/src/com/avaje/ebean/server/transaction/TableModInfo.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/server/transaction/TableModInfo.java Sun Feb 22 11:37:22 CET 2009
@@ -76,7 +76,7 @@
}

public int hashCode() {
- int hc = TableModInfo.class.hashCode();
+ int hc = TableModInfo.class.getName().hashCode();
hc = hc*31 + tableName.hashCode();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/LogicExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/LogicExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/LogicExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -61,7 +61,7 @@
* Based on the joinType plus the two expressions.
*/
public int queryPlanHash() {
- int hc = LogicExpression.class.hashCode() + joinType.hashCode();
+ int hc = LogicExpression.class.getName().hashCode() + joinType.hashCode();
hc = hc * 31 + expOne.queryPlanHash();
hc = hc * 31 + expTwo.queryPlanHash();
return hc;
Index: ../ebean/src/com/avaje/ebean/util/DefaultExpressionList.java
===================================================================
--- ../ebean/src/com/avaje/ebean/util/DefaultExpressionList.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/util/DefaultExpressionList.java Sun Feb 22 11:37:22 CET 2009
@@ -1,11 +1,5 @@
package com.avaje.ebean.util;

-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryListener;
import com.avaje.ebean.expression.Expr;
@@ -15,6 +9,12 @@
import com.avaje.ebean.expression.InternalExpressionList;
import com.avaje.ebean.expression.Junction;

+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* Default implementation of ExpressionList.
*/
@@ -125,7 +125,7 @@
* Calculate a hash based on the expressions but excluding the actual bind values.
*/
public int queryPlanHash() {
- int hash = DefaultExpressionList.class.hashCode();
+ int hash = DefaultExpressionList.class.getName().hashCode();
for (int i = 0, size=list.size(); i < size; i++) {
Expression expression = list.get(i);
hash = hash*31 + expression.queryPlanHash();
@@ -137,7 +137,7 @@
* Calculate a hash based on the expressions.
*/
public int queryBindHash() {
- int hash = DefaultExpressionList.class.hashCode();
+ int hash = DefaultExpressionList.class.getName().hashCode();
for (int i = 0, size=list.size(); i < size; i++) {
Expression expression = list.get(i);
hash = hash*31 + expression.queryBindHash();
Index: ../ebean/src/com/avaje/ebean/server/net/Endpoint.java
===================================================================
--- ../ebean/src/com/avaje/ebean/server/net/Endpoint.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/server/net/Endpoint.java Sun Feb 22 11:37:22 CET 2009
@@ -81,7 +81,7 @@
}

public int hashCode() {
- int hc = Endpoint.class.hashCode();
+ int hc = Endpoint.class.getName().hashCode();
hc = 31*hc + fullName.hashCode();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/AllEqualsExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/AllEqualsExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/AllEqualsExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -74,7 +74,7 @@
*


*/
public int queryPlanHash() {
- int hc = AllEqualsExpression.class.hashCode();
+ int hc = AllEqualsExpression.class.getName().hashCode();
Set> entries = propMap.entrySet();
Iterator> it = entries.iterator();

Index: ../ebean/src/com/avaje/ebean/query/DefaultOrmQuery.java
===================================================================
--- ../ebean/src/com/avaje/ebean/query/DefaultOrmQuery.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/query/DefaultOrmQuery.java Sun Feb 22 11:38:27 CET 2009
@@ -1,12 +1,5 @@
package com.avaje.ebean.query;

-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.persistence.PersistenceException;
-
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryListener;
@@ -25,6 +18,12 @@
import com.avaje.ebean.util.BindParams;
import com.avaje.ebean.util.DefaultExpressionList;

+import javax.persistence.PersistenceException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* Default implementation of an Object Relational query.
*/
@@ -317,7 +316,7 @@
}

public int hashCode() {
- int hc = Query.class.hashCode();
+ int hc = Query.class.getName().hashCode();
hc = hc * 31 + getQueryHash();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/NotExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/NotExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/NotExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -31,7 +31,7 @@
* Based on the expression.
*/
public int queryPlanHash() {
- int hc = NotExpression.class.hashCode();
+ int hc = NotExpression.class.getName().hashCode();
hc = hc * 31 + exp.queryPlanHash();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/CaseInsensitiveEqualExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/CaseInsensitiveEqualExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/CaseInsensitiveEqualExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -31,7 +31,7 @@
* Based on the propertyName.
*/
public int queryPlanHash() {
- int hc = CaseInsensitiveEqualExpression.class.hashCode();
+ int hc = CaseInsensitiveEqualExpression.class.getName().hashCode();
hc = hc * 31 + propertyName.hashCode();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/LikeExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/LikeExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/LikeExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -44,7 +44,7 @@
* Based on caseInsensitive and the property name.
*/
public int queryPlanHash() {
- int hc = LikeExpression.class.hashCode();
+ int hc = LikeExpression.class.getName().hashCode();
hc = hc * 31 + (caseInsensitive ? 0 : 1);
hc = hc * 31 + propertyName.hashCode();
return hc;
Index: ../ebean/src/com/avaje/ebean/expression/NullExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/NullExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/NullExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -39,7 +39,7 @@
* Based on notNull flag and the propertyName.
*/
public int queryPlanHash() {
- int hc = NullExpression.class.hashCode();
+ int hc = NullExpression.class.getName().hashCode();
hc = hc * 31 + (notNull ? 1 : 0);
hc = hc * 31 + propertyName.hashCode();
return hc;
Index: ../ebean/src/com/avaje/ebean/expression/SimpleExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/SimpleExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/SimpleExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -66,9 +66,9 @@
* Based on the type and propertyName.
*/
public int queryPlanHash() {
- int hc = SimpleExpression.class.hashCode();
+ int hc = SimpleExpression.class.getName().hashCode();
hc = hc * 31 + propertyName.hashCode();
- hc = hc * 31 + type.hashCode();
+ hc = hc * 31 + type.name().hashCode();
return hc;
}

Index: ../ebean/src/com/avaje/ebean/expression/RawExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/RawExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/RawExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -34,7 +34,7 @@
* Based on the sql.
*/
public int queryPlanHash() {
- int hc = RawExpression.class.hashCode();
+ int hc = RawExpression.class.getName().hashCode();
hc = hc * 31 + sql.hashCode();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/BetweenExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/BetweenExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/BetweenExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -37,7 +37,7 @@
* Based on the property name.
*/
public int queryPlanHash() {
- int hc = BetweenExpression.class.hashCode();
+ int hc = BetweenExpression.class.getName().hashCode();
hc = hc * 31 + propertyName.hashCode();
return hc;
}
Index: ../ebean/src/com/avaje/ebean/expression/InExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/InExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/InExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -45,7 +45,7 @@
* Based on the number of values in the in clause.
*/
public int queryPlanHash() {
- return InExpression.class.hashCode() + 31 * values.length;
+ return InExpression.class.getName().hashCode() + 31 * values.length;
}

public int queryBindHash() {
Index: ../ebean/src/com/avaje/ebean/expression/JunctionExpression.java
===================================================================
--- ../ebean/src/com/avaje/ebean/expression/JunctionExpression.java (revision 141)
+++ ../ebean/src/com/avaje/ebean/expression/JunctionExpression.java Sun Feb 22 11:37:22 CET 2009
@@ -72,7 +72,7 @@
* Based on Junction type and all the expression contained.
*/
public int queryPlanHash() {
- int hc = JunctionExpression.class.hashCode();
+ int hc = JunctionExpression.class.getName().hashCode();
for (int i = 0; i < list.size(); i++) {
hc = hc * 31 + joinType.hashCode();
hc = hc * 31 + list.get(i).queryPlanHash();
@@ -82,7 +82,7 @@
}

public int queryBindHash() {
- int hc = JunctionExpression.class.hashCode();
+ int hc = JunctionExpression.class.getName().hashCode();
for (int i = 0; i < list.size(); i++) {
hc = hc * 31 + list.get(i).queryBindHash();
}

 
Rob 23 Feb 03:39
Yes, I buy that...

Yes I follow that and the fix(s) look correct.

Thanks, Rob.

Rob 24 Feb 10:17
Committed changes

I have committed the changes into HEAD.

woResponse

Upload a file