Bug 494408 - Memory leak in EntityManager.createQuery
Signed-off-by: David Kral <david.k.kral@oracle.com>
Reviewed-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/criteria/AdvancedCriteriaQueryTestSuite.java b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/criteria/AdvancedCriteriaQueryTestSuite.java
index 858630c..06ed186 100644
--- a/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/criteria/AdvancedCriteriaQueryTestSuite.java
+++ b/jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/criteria/AdvancedCriteriaQueryTestSuite.java
@@ -18,6 +18,7 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashSet;
@@ -57,6 +58,8 @@
import org.eclipse.persistence.config.ResultSetType;
import org.eclipse.persistence.config.ResultType;
import org.eclipse.persistence.internal.jpa.querydef.CompoundExpressionImpl;
+import org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl;
+import org.eclipse.persistence.internal.jpa.querydef.FromImpl;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaCriteriaBuilder;
import org.eclipse.persistence.jpa.JpaQuery;
@@ -171,6 +174,7 @@ public static Test suite() {
suite.addTest(new AdvancedCriteriaQueryTestSuite("testUnusedJoinDoesNotAffectFetchJoin"));
// Bug 464833
suite.addTest(new AdvancedCriteriaQueryTestSuite("testGetRestrictionReturningCorrectPredicate"));
+ suite.addTest(new AdvancedCriteriaQueryTestSuite("testJoinDuplication"));
return suite;
}
@@ -1869,4 +1873,33 @@ public void testGetRestrictionReturningCorrectPredicate() {
}
}
+ /**
+ * Test that checks duplicating of joins
+ */
+ public void testJoinDuplication() throws NoSuchFieldException, IllegalAccessException {
+ EntityManager em = createEntityManager();
+ beginTransaction(em);
+ try {
+ CriteriaBuilder qb = em.getCriteriaBuilder();
+ CriteriaQuery<Employee>cq = qb.createQuery(Employee.class);
+ Root<Employee> root = cq.from(Employee.class);
+ root.join("manager");
+
+ em.createQuery(cq);
+ Field field = cq.getClass().getDeclaredField("joins");
+ field.setAccessible(true);
+ Set<FromImpl> value = (Set<FromImpl>) field.get(cq);
+ assertEquals(1, value.size());
+
+ em.createQuery(cq);
+ ((CriteriaQueryImpl<Employee>)cq).translate();
+ value = (Set<FromImpl>) field.get(cq);
+ assertEquals(1, value.size());
+ } finally {
+ rollbackTransaction(em);
+ closeEntityManager(em);
+ }
+ }
+
+
}
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java
index 69071d1..1373e29 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java
@@ -16,9 +16,7 @@
import java.lang.reflect.Constructor;
import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaQuery;
@@ -61,7 +59,7 @@ public class CriteriaQueryImpl<T> extends AbstractQueryImpl<T> implements Criter
protected SelectionImpl<?> selection;
protected List<Order> orderBy;
- protected List<FromImpl> joins;
+ protected Set<FromImpl> joins;
public CriteriaQueryImpl(Metamodel metamodel, ResultType queryResult, Class result, CriteriaBuilderImpl queryBuilder) {
super(metamodel, queryResult, queryBuilder, result);
@@ -447,7 +445,7 @@ public CriteriaQuery<T> distinct(boolean distinct) {
@Override
public void addJoin(FromImpl from) {
if (this.joins == null) {
- this.joins = new ArrayList<FromImpl>();
+ this.joins = new HashSet<FromImpl>();
}
this.joins.add(from);
}