mirror of
https://github.com/querydsl/querydsl.git
synced 2026-06-30 21:08:30 +08:00
Merge pull request #2530 from jwgmeligmeyling/jpa-treated-path
[#658] Support JPQL Treated paths for WHERE clause
This commit is contained in:
commit
c75ef4cafd
3
pom.xml
3
pom.xml
@ -291,6 +291,9 @@
|
||||
<exclude>com/querydsl/sql/types/LocalDateTimeType</exclude>
|
||||
<exclude>com/querydsl/sql/types/LocalDateType</exclude>
|
||||
<exclude>com/querydsl/sql/types/LocalTimeType</exclude>
|
||||
<exclude>com/querydsl/jpa/Hibernate5Templates</exclude>
|
||||
<exclude>com/querydsl/jpa/HibernateHandler</exclude>
|
||||
<exclude>com/querydsl/jpa/JPAExpressions</exclude>
|
||||
</excludes>
|
||||
<compatibilityType>BACKWARD_COMPATIBLE_USER</compatibilityType>
|
||||
<dumpDetails>true</dumpDetails>
|
||||
|
||||
@ -65,7 +65,12 @@ public enum PathType implements Operator {
|
||||
/**
|
||||
* Root path
|
||||
*/
|
||||
VARIABLE;
|
||||
VARIABLE,
|
||||
|
||||
/**
|
||||
* Treated path
|
||||
*/
|
||||
TREATED_PATH;
|
||||
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
|
||||
@ -17,11 +17,19 @@ import com.querydsl.core.Tuple;
|
||||
import com.querydsl.core.types.CollectionExpression;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.core.types.Expression;
|
||||
import com.querydsl.core.types.ExpressionException;
|
||||
import com.querydsl.core.types.Ops;
|
||||
import com.querydsl.core.types.PathMetadata;
|
||||
import com.querydsl.core.types.PathType;
|
||||
import com.querydsl.core.types.dsl.BeanPath;
|
||||
import com.querydsl.core.types.dsl.ComparableExpression;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.core.types.dsl.StringExpression;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
||||
/**
|
||||
* {@code JPAExpressions} provides factory methods for JPQL specific operations
|
||||
* elements.
|
||||
@ -102,6 +110,31 @@ public final class JPAExpressions {
|
||||
return select(expr).from(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JPA 2.1 treated path.
|
||||
*
|
||||
* @param path The path to apply the treat operation on
|
||||
* @param subtype subtype class
|
||||
* @param <U> the subtype class
|
||||
* @param <T> the expression type
|
||||
* @return subtype instance with the same identity
|
||||
*/
|
||||
public static <U extends BeanPath<? extends T>, T> U treat(BeanPath<? extends T> path, Class<U> subtype) {
|
||||
try {
|
||||
Class<? extends T> entitySubType = getConcreteEntitySubType(subtype);
|
||||
PathMetadata pathMetadata = new PathMetadata(path, getEntityName(entitySubType), PathType.TREATED_PATH);
|
||||
return subtype.getConstructor(PathMetadata.class).newInstance(pathMetadata);
|
||||
} catch (InstantiationException e) {
|
||||
throw new ExpressionException(e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ExpressionException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new ExpressionException(e.getMessage(), e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExpressionException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a avg(col) expression
|
||||
*
|
||||
@ -142,6 +175,22 @@ public final class JPAExpressions {
|
||||
return Expressions.stringOperation(JPQLOps.TYPE, path);
|
||||
}
|
||||
|
||||
private static 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 static <U extends BeanPath<? extends T>, T> Class<? extends T> getConcreteEntitySubType(Class<U> subtype) {
|
||||
return (Class<? extends T>) ((ParameterizedType) subtype.getGenericSuperclass()).getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private JPAExpressions() { }
|
||||
|
||||
}
|
||||
|
||||
@ -144,6 +144,7 @@ public class JPQLTemplates extends Templates {
|
||||
// path types
|
||||
add(PathType.PROPERTY, "{0}.{1s}");
|
||||
add(PathType.VARIABLE, "{0s}");
|
||||
add(PathType.TREATED_PATH, "treat({0} as {1s})");
|
||||
|
||||
// case for eq
|
||||
add(Ops.CASE_EQ, "case {1} end");
|
||||
|
||||
@ -23,6 +23,7 @@ import org.junit.Test;
|
||||
import com.querydsl.core.DefaultQueryMetadata;
|
||||
import com.querydsl.core.JoinType;
|
||||
import com.querydsl.core.QueryMetadata;
|
||||
import com.querydsl.core.domain.QAnimal;
|
||||
import com.querydsl.core.domain.QCat;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.core.types.Expression;
|
||||
@ -253,6 +254,21 @@ public class JPQLSerializerTest {
|
||||
" inner join treat(cat.mate as DomesticCat) as domesticCat", serializer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void treated_path() {
|
||||
QAnimal animal = QAnimal.animal;
|
||||
JPQLSerializer serializer = new JPQLSerializer(HQLTemplates.DEFAULT);
|
||||
QueryMetadata md = new DefaultQueryMetadata();
|
||||
md.addJoin(JoinType.DEFAULT, animal);
|
||||
|
||||
md.addWhere(JPAExpressions.treat(animal, QCat.class).breed.eq(1));
|
||||
md.setProjection(animal);
|
||||
serializer.serialize(md, false, null);
|
||||
assertEquals("select animal\n" +
|
||||
"from Animal animal\n" +
|
||||
"where treat(animal as Cat).breed = ?1", serializer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openJPA_variables() {
|
||||
QCat cat = QCat.cat;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user