diff --git a/querydsl-jpa/pom.xml b/querydsl-jpa/pom.xml index 8006c0f09..f2e3a1237 100644 --- a/querydsl-jpa/pom.xml +++ b/querydsl-jpa/pom.xml @@ -1,4 +1,4 @@ - + 4.0.0 @@ -16,8 +16,8 @@ jar - 4.2.0.Final - 4.3.0.Final + 4.3.5.Final + 4.3.1.Final 2.5.1 @@ -59,7 +59,7 @@ org.hibernate.javax.persistence - hibernate-jpa-2.0-api + hibernate-jpa-2.1-api 1.0.0.Final provided @@ -342,4 +342,4 @@ - + diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLOps.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLOps.java index e96da04a9..16d222879 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLOps.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLOps.java @@ -24,6 +24,8 @@ public final class JPQLOps { private static final String NS = JPQLOps.class.getName(); + public static final Operator TREAT = new OperatorImpl(NS, "TREAT"); + public static final Operator INDEX = new OperatorImpl(NS, "INDEX"); public static final Operator TYPE = new OperatorImpl(NS, "TYPE"); diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java index 0d2cc5790..d4eda0958 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java @@ -13,50 +13,22 @@ */ package com.mysema.query.jpa; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nullable; -import javax.persistence.DiscriminatorValue; -import javax.persistence.Entity; -import javax.persistence.EntityManager; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.PersistenceUnitUtil; -import javax.persistence.metamodel.EntityType; -import javax.persistence.metamodel.Metamodel; -import javax.persistence.metamodel.SingularAttribute; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.mysema.query.JoinExpression; import com.mysema.query.JoinType; import com.mysema.query.QueryMetadata; import com.mysema.query.support.SerializerBase; -import com.mysema.query.types.Constant; -import com.mysema.query.types.ConstantImpl; -import com.mysema.query.types.EntityPath; -import com.mysema.query.types.Expression; -import com.mysema.query.types.ExpressionUtils; -import com.mysema.query.types.FactoryExpression; -import com.mysema.query.types.Operation; -import com.mysema.query.types.Operator; -import com.mysema.query.types.Ops; -import com.mysema.query.types.Order; -import com.mysema.query.types.OrderSpecifier; -import com.mysema.query.types.ParamExpression; -import com.mysema.query.types.Path; -import com.mysema.query.types.PathImpl; -import com.mysema.query.types.PathType; -import com.mysema.query.types.Predicate; -import com.mysema.query.types.SubQueryExpression; +import com.mysema.query.types.*; import com.mysema.util.MathUtils; +import javax.annotation.Nullable; +import javax.persistence.*; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.Metamodel; +import javax.persistence.metamodel.SingularAttribute; +import java.util.*; + /** * JPQLSerializer serializes Querydsl expressions into JPQL syntax. * @@ -127,25 +99,54 @@ public class JPQLSerializer extends SerializerBase { this.entityManager = em; } + private String getEntityName(Class clazz) { + final Entity entityAnnotation = clazz.getAnnotation(Entity.class); + if (entityAnnotation != null && entityAnnotation.name().length() > 0) { + return entityAnnotation.name(); + } else if (clazz.getPackage() != null) { + String pn = clazz.getPackage().getName(); + return clazz.getName().substring(pn.length() + 1); + } else { + return clazz.getName(); + } + } + private void handleJoinTarget(JoinExpression je) { // type specifier if (je.getTarget() instanceof EntityPath) { final EntityPath pe = (EntityPath) je.getTarget(); if (pe.getMetadata().isRoot()) { - final Entity entityAnnotation = pe.getAnnotatedElement().getAnnotation(Entity.class); - if (entityAnnotation != null && entityAnnotation.name().length() > 0) { - append(entityAnnotation.name()); - } else if (pe.getType().getPackage() != null) { - final String pn = pe.getType().getPackage().getName(); - final String typeName = pe.getType().getName().substring(pn.length() + 1); - append(typeName); - } else { - append(pe.getType().getName()); - } + append(getEntityName(pe.getType())); append(" "); } + handle(je.getTarget()); + } else if (je.getTarget() instanceof Operation) { + Operation op = (Operation)je.getTarget(); + if (op.getOperator() == Ops.ALIAS) { + boolean treat = false; + if (Collection.class.isAssignableFrom(op.getArg(0).getType())) { + if (op.getArg(0) instanceof CollectionExpression) { + Class par = ((CollectionExpression)op.getArg(0)).getParameter(0); + treat = !par.equals(op.getArg(1).getType()); + } + } else if (Map.class.isAssignableFrom(op.getArg(0).getType())) { + if (op.getArg(0) instanceof MapExpression) { + Class par = ((MapExpression)op.getArg(0)).getParameter(1); + treat = !par.equals(op.getArg(1).getType()); + } + } else { + treat = !op.getArg(0).getType().equals(op.getArg(1).getType()); + } + if (treat) { + Expression entityName = ConstantImpl.create(getEntityName(op.getArg(1).getType())); + Expression t = OperationImpl.create(op.getType(), JPQLOps.TREAT, op.getArg(0), entityName); + op = OperationImpl.create(op.getType(), Ops.ALIAS, t, op.getArg(1)); + } + } + handle(op); + } else { + handle(je.getTarget()); } - handle(je.getTarget()); } public void serialize(QueryMetadata metadata, boolean forCountRow, @Nullable String projection) { diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLTemplates.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLTemplates.java index afaa5775e..c4dcf8bf8 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLTemplates.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLTemplates.java @@ -13,13 +13,13 @@ */ package com.mysema.query.jpa; -import javax.annotation.Nullable; - import com.mysema.query.types.Operator; import com.mysema.query.types.Ops; import com.mysema.query.types.PathType; import com.mysema.query.types.Templates; +import javax.annotation.Nullable; + /** * JPQLTemplates extends {@link Templates} to provide operator patterns for JPQL * serialization @@ -130,8 +130,8 @@ public class JPQLTemplates extends Templates { add(Ops.INSTANCE_OF, "type({0}) = {1}"); add(JPQLOps.TYPE, "type({0})"); - add(JPQLOps.INDEX, "index({0})"); + add(JPQLOps.TREAT, "treat({0} as {1s})"); //CHECKSTYLE:ON } diff --git a/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java b/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java index 38a3bed03..3b3934cf4 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java @@ -13,38 +13,8 @@ */ package com.mysema.query; -import static com.mysema.query.Target.DERBY; -import static com.mysema.query.Target.HSQLDB; -import static com.mysema.query.Target.MYSQL; -import static com.mysema.query.Target.ORACLE; -import static com.mysema.query.Target.TERADATA; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - import antlr.RecognitionException; import antlr.TokenStreamException; - import com.google.common.collect.Lists; import com.mysema.commons.lang.Pair; import com.mysema.query.group.Group; @@ -53,67 +23,29 @@ import com.mysema.query.group.QPair; import com.mysema.query.jpa.JPAExpressions; import com.mysema.query.jpa.JPASubQuery; import com.mysema.query.jpa.JPQLQuery; -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.Color; -import com.mysema.query.jpa.domain.Company; +import com.mysema.query.jpa.domain.*; import com.mysema.query.jpa.domain.Company.Rating; -import com.mysema.query.jpa.domain.DomesticCat; -import com.mysema.query.jpa.domain.DoubleProjection; -import com.mysema.query.jpa.domain.Employee; -import com.mysema.query.jpa.domain.Entity1; -import com.mysema.query.jpa.domain.Entity2; -import com.mysema.query.jpa.domain.FloatProjection; -import com.mysema.query.jpa.domain.Foo; -import com.mysema.query.jpa.domain.JobFunction; -import com.mysema.query.jpa.domain.Numeric; -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.QCompany; -import com.mysema.query.jpa.domain.QDoubleProjection; -import com.mysema.query.jpa.domain.QEmployee; -import com.mysema.query.jpa.domain.QEntity1; -import com.mysema.query.jpa.domain.QFloatProjection; -import com.mysema.query.jpa.domain.QFoo; -import com.mysema.query.jpa.domain.QHuman; -import com.mysema.query.jpa.domain.QMammal; -import com.mysema.query.jpa.domain.QNumeric; -import com.mysema.query.jpa.domain.QShow; -import com.mysema.query.jpa.domain.QSimpleTypes; -import com.mysema.query.jpa.domain.QUser; -import com.mysema.query.jpa.domain.QWorld; -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.HibernateSubQuery; import com.mysema.query.support.Expressions; -import com.mysema.query.types.ArrayConstructorExpression; -import com.mysema.query.types.Concatenation; -import com.mysema.query.types.ConstructorExpression; -import com.mysema.query.types.EntityPath; -import com.mysema.query.types.Expression; -import com.mysema.query.types.ExpressionUtils; -import com.mysema.query.types.ParamNotSetException; -import com.mysema.query.types.Path; -import com.mysema.query.types.Predicate; -import com.mysema.query.types.Projections; -import com.mysema.query.types.QTuple; -import com.mysema.query.types.expr.BooleanExpression; -import com.mysema.query.types.expr.ListExpression; -import com.mysema.query.types.expr.Param; -import com.mysema.query.types.expr.SimpleExpression; -import com.mysema.query.types.expr.StringExpression; -import com.mysema.query.types.path.EnumPath; -import com.mysema.query.types.path.ListPath; -import com.mysema.query.types.path.NumberPath; -import com.mysema.query.types.path.SimplePath; -import com.mysema.query.types.path.StringPath; +import com.mysema.query.types.*; +import com.mysema.query.types.expr.*; +import com.mysema.query.types.path.*; import com.mysema.testutil.ExcludeIn; import com.mysema.testutil.IncludeIn; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; +import java.util.Calendar; +import java.util.Map.Entry; + +import static com.mysema.query.Target.*; +import static org.junit.Assert.*; /** * @author tiwe @@ -441,7 +373,7 @@ public abstract class AbstractJPATest { } } - @Test(expected=NullPointerException.class) + @Test(expected=ClassCastException.class) @NoEclipseLink @NoBatooJPA public void Constant_Hibernate() { @@ -1483,6 +1415,17 @@ public abstract class AbstractJPATest { } } + @Test + @NoBatooJPA + @NoEclipseLink + public void Treat() { + QDomesticCat domesticCat = QDomesticCat.domesticCat; + query().from(cat) + .innerJoin(cat.mate, domesticCat._super) + .where(domesticCat.name.eq("Bobby")) + .count(); + } + @Test @Ignore public void Type() { @@ -1490,7 +1433,6 @@ public abstract class AbstractJPATest { query().from(animal).orderBy(animal.id.asc()).list(JPAExpressions.type(animal))); } - @Test @NoOpenJPA public void Type_Order() { diff --git a/querydsl-jpa/src/test/java/com/mysema/query/JPABase.java b/querydsl-jpa/src/test/java/com/mysema/query/JPABase.java index 933fb1a30..84786d2e8 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/JPABase.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/JPABase.java @@ -13,39 +13,30 @@ */ package com.mysema.query; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.sql.Connection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.persistence.EntityManager; -import javax.persistence.FlushModeType; -import javax.persistence.LockModeType; - -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.runner.RunWith; - import com.mysema.commons.lang.CloseableIterator; import com.mysema.query.jpa.JPASubQuery; -import com.mysema.query.jpa.domain.Cat; -import com.mysema.query.jpa.domain.QCat; -import com.mysema.query.jpa.domain.QCatSummary; -import com.mysema.query.jpa.domain.QChild; -import com.mysema.query.jpa.domain.QParent; +import com.mysema.query.jpa.domain.*; import com.mysema.query.jpa.impl.JPADeleteClause; import com.mysema.query.jpa.impl.JPAQuery; import com.mysema.query.types.EntityPath; import com.mysema.query.types.expr.BooleanExpression; import com.mysema.testutil.ExcludeIn; import com.mysema.testutil.JPATestRunner; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.MethodRule; +import org.junit.runner.RunWith; + +import javax.persistence.EntityManager; +import javax.persistence.FlushModeType; +import javax.persistence.LockModeType; +import java.sql.Connection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; /** * @author tiwe @@ -88,7 +79,9 @@ public class JPABase extends AbstractJPATest { } @Test - @NoEclipseLink @NoOpenJPA + @NoEclipseLink + @NoOpenJPA + @NoHibernate public void Connection_Access() { assertNotNull(query().from(cat).createQuery(cat).unwrap(Connection.class)); } diff --git a/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLSerializerTest.java b/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLSerializerTest.java index 6e14eebee..d87df061e 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLSerializerTest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLSerializerTest.java @@ -13,25 +13,26 @@ */ package com.mysema.query.jpa; -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; - -import org.junit.Test; - import com.mysema.query.DefaultQueryMetadata; import com.mysema.query.JoinType; import com.mysema.query.QueryMetadata; import com.mysema.query.domain.QCat; import com.mysema.query.jpa.domain.Location; +import com.mysema.query.jpa.domain.QDomesticCat; import com.mysema.query.jpa.domain.QEmployee; import com.mysema.query.support.Expressions; import com.mysema.query.types.EntityPath; import com.mysema.query.types.Expression; +import com.mysema.query.types.Path; import com.mysema.query.types.Predicate; import com.mysema.query.types.path.EntityPathBase; import com.mysema.query.types.path.NumberPath; import com.mysema.query.types.path.StringPath; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; public class JPQLSerializerTest { @@ -196,4 +197,18 @@ public class JPQLSerializerTest { "from Cat cat\n" + "order by cat.name asc nulls last", serializer.toString()); } + + @Test + public void Treat() { + QCat cat = QCat.cat; + JPQLSerializer serializer = new JPQLSerializer(HQLTemplates.DEFAULT); + QueryMetadata md = new DefaultQueryMetadata(); + md.addJoin(JoinType.DEFAULT, cat); + md.addJoin(JoinType.JOIN, cat.mate.as((Path)QDomesticCat.domesticCat)); + md.addProjection(QDomesticCat.domesticCat); + serializer.serialize(md, false, null); + assertEquals("select domesticCat\n" + + "from Cat cat\n" + + " inner join treat(cat.mate as DomesticCat) as domesticCat", serializer.toString()); + } } diff --git a/querydsl-jpa/src/test/java/com/mysema/testutil/HibernateTestRunner.java b/querydsl-jpa/src/test/java/com/mysema/testutil/HibernateTestRunner.java index 408c2ad40..699941473 100644 --- a/querydsl-jpa/src/test/java/com/mysema/testutil/HibernateTestRunner.java +++ b/querydsl-jpa/src/test/java/com/mysema/testutil/HibernateTestRunner.java @@ -13,13 +13,8 @@ */ package com.mysema.testutil; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.List; -import java.util.Properties; - +import com.mysema.query.Mode; +import com.mysema.query.jpa.domain.Domain; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; @@ -34,8 +29,12 @@ import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; -import com.mysema.query.Mode; -import com.mysema.query.jpa.domain.Domain; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; /** * @author tiwe @@ -109,7 +108,7 @@ public class HibernateTestRunner extends BlockJUnit4ClassRunner { props.load(is); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(props) - .buildServiceRegistry(); + .build(); cfg.setProperties(props); sessionFactory = cfg.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession();