From b4863a78f39401e830d56f0851180f0ac48b462b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Fri, 23 Mar 2012 23:31:51 +0200 Subject: [PATCH] #117 improved GroupBy handling --- .../query/jpa/impl/AbstractJPAQuery.java | 61 +++++++++++-------- .../mysema/query/AbstractHibernateTest.java | 31 ---------- .../mysema/query/AbstractStandardTest.java | 41 +++++++++++++ 3 files changed, 75 insertions(+), 58 deletions(-) diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/impl/AbstractJPAQuery.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/impl/AbstractJPAQuery.java index cd62e1ef1..2cea88d12 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/impl/AbstractJPAQuery.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/impl/AbstractJPAQuery.java @@ -40,8 +40,10 @@ import com.mysema.query.SearchResults; import com.mysema.query.jpa.HQLTemplates; import com.mysema.query.jpa.JPQLQueryBase; import com.mysema.query.jpa.JPQLTemplates; +import com.mysema.query.jpa.hibernate.FactoryExpressionTransformer; import com.mysema.query.types.Expression; import com.mysema.query.types.FactoryExpression; +import com.mysema.query.types.FactoryExpressionUtils; /** * Abstract base class for JPA API based implementations of the JPQLQuery interface @@ -157,34 +159,39 @@ public abstract class AbstractJPAQuery> extends JP // set transformer, if necessary and possible List> projection = getMetadata().getProjection(); - if (projection.size() == 1 && !forCount) { - Expression expr = projection.get(0); - if (expr instanceof FactoryExpression) { - String transformation = null; - if (hibernateQueryClass != null && hibernateQueryClass.isInstance(query)) { - transformation = "com.mysema.query.jpa.impl.HibernateQueryTransformation"; + + FactoryExpression wrapped = projection.size() > 1 ? FactoryExpressionUtils.wrap(projection) : null; + + if (!forCount && ((projection.size() == 1 && projection.get(0) instanceof FactoryExpression) || wrapped != null)) { + Expression expr = wrapped != null ? wrapped : projection.get(0); + String transformation = null; + if (hibernateQueryClass != null && hibernateQueryClass.isInstance(query)) { + transformation = "com.mysema.query.jpa.impl.HibernateQueryTransformation"; + } +// else if (query.getClass().getName().startsWith("org.eclipse.persistence")) { +// transformation = "com.mysema.query.jpa.impl.EclipseLinkQueryTransformation"; +// } + if (transformation != null) { + try { + Constructor c = Class.forName(transformation).getConstructor(Query.class, FactoryExpression.class); + c.newInstance(query, expr); + } catch (NoSuchMethodException e) { + throw new QueryException(e); + } catch (ClassNotFoundException e) { + throw new QueryException(e); + } catch (InstantiationException e) { + throw new QueryException(e); + } catch (IllegalAccessException e) { + throw new QueryException(e); + } catch (InvocationTargetException e) { + throw new QueryException(e); } -// else if (query.getClass().getName().startsWith("org.eclipse.persistence")) { -// transformation = "com.mysema.query.jpa.impl.EclipseLinkQueryTransformation"; -// } - if (transformation != null) { - try { - Constructor c = Class.forName(transformation).getConstructor(Query.class, FactoryExpression.class); - c.newInstance(query, expr); - } catch (NoSuchMethodException e) { - throw new QueryException(e); - } catch (ClassNotFoundException e) { - throw new QueryException(e); - } catch (InstantiationException e) { - throw new QueryException(e); - } catch (IllegalAccessException e) { - throw new QueryException(e); - } catch (InvocationTargetException e) { - throw new QueryException(e); - } - - } else { - factoryExpressionUsed = true; + + } else { + factoryExpressionUsed = true; + if (wrapped != null) { + getMetadata().clearProjection(); + getMetadata().addProjection(wrapped); } } } diff --git a/querydsl-jpa/src/test/java/com/mysema/query/AbstractHibernateTest.java b/querydsl-jpa/src/test/java/com/mysema/query/AbstractHibernateTest.java index f87e214b8..6faedb3d6 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/AbstractHibernateTest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/AbstractHibernateTest.java @@ -118,36 +118,5 @@ public abstract class AbstractHibernateTest extends AbstractStandardTest{ rows.close(); } - @Test - public void GroupBy() { - QAuthor author = QAuthor.author; - QBook book = QBook.book; - for (int i = 0; i < 10; i++) { - Author a = new Author(); - a.setName(String.valueOf(i)); - session.save(a); - for (int j = 0; j < 2; j++) { - Book b = new Book(); - b.setTitle(String.valueOf(i)+" "+String.valueOf(j)); - b.setAuthor(a); - session.save(b); - } - } - - Map>> map = new HibernateQuery(session) - .from(author) - .join(author.books, book) - .transform(GroupBy - .groupBy(author.id) - .as(GroupBy.list(QPair.create(book.id, book.title)))); - - for (Entry>> entry : map.entrySet()) { - System.out.println("author = " + entry.getKey()); - - for (Pair pair : entry.getValue()) { - System.out.println(" book = " + pair.getFirst() + "," + pair.getSecond()); - } - } - } } diff --git a/querydsl-jpa/src/test/java/com/mysema/query/AbstractStandardTest.java b/querydsl-jpa/src/test/java/com/mysema/query/AbstractStandardTest.java index e7ed1cdf6..0ee0caf01 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/AbstractStandardTest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/AbstractStandardTest.java @@ -28,7 +28,9 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.Map.Entry; import org.junit.Before; import org.junit.Ignore; @@ -38,16 +40,22 @@ import antlr.RecognitionException; import antlr.TokenStreamException; import com.mysema.commons.lang.Pair; +import com.mysema.query.group.GroupBy; +import com.mysema.query.group.QPair; import com.mysema.query.jpa.JPQLGrammar; import com.mysema.query.jpa.JPQLQuery; import com.mysema.query.jpa.JPQLSubQuery; import com.mysema.query.jpa.domain.Animal; +import com.mysema.query.jpa.domain.Author; +import com.mysema.query.jpa.domain.Book; import com.mysema.query.jpa.domain.Cat; import com.mysema.query.jpa.domain.DomesticCat; import com.mysema.query.jpa.domain.Employee; import com.mysema.query.jpa.domain.Foo; import com.mysema.query.jpa.domain.JobFunction; import com.mysema.query.jpa.domain.QAnimal; +import com.mysema.query.jpa.domain.QAuthor; +import com.mysema.query.jpa.domain.QBook; import com.mysema.query.jpa.domain.QCat; import com.mysema.query.jpa.domain.QEmployee; import com.mysema.query.jpa.domain.QFoo; @@ -56,6 +64,7 @@ import com.mysema.query.jpa.domain.QUser; import com.mysema.query.jpa.domain.Show; import com.mysema.query.jpa.domain4.QBookMark; import com.mysema.query.jpa.domain4.QBookVersion; +import com.mysema.query.jpa.hibernate.HibernateQuery; import com.mysema.query.jpa.hibernate.HibernateSubQuery; import com.mysema.query.types.ArrayConstructorExpression; import com.mysema.query.types.Concatenation; @@ -686,4 +695,36 @@ public abstract class AbstractStandardTest { assertTrue(strings.contains("b")); } + @Test + public void GroupBy() { + QAuthor author = QAuthor.author; + QBook book = QBook.book; + + for (int i = 0; i < 10; i++) { + Author a = new Author(); + a.setName(String.valueOf(i)); + save(a); + for (int j = 0; j < 2; j++) { + Book b = new Book(); + b.setTitle(String.valueOf(i)+" "+String.valueOf(j)); + b.setAuthor(a); + save(b); + } + } + + Map>> map = query() + .from(author) + .join(author.books, book) + .transform(GroupBy + .groupBy(author.id) + .as(GroupBy.list(QPair.create(book.id, book.title)))); + + for (Entry>> entry : map.entrySet()) { + System.out.println("author = " + entry.getKey()); + + for (Pair pair : entry.getValue()) { + System.out.println(" book = " + pair.getFirst() + "," + pair.getSecond()); + } + } + } }