mirror of
https://github.com/querydsl/querydsl.git
synced 2026-06-27 21:01:15 +08:00
Add enum conversion #575
This commit is contained in:
parent
3204eb8d63
commit
866523a4f1
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2012, Mysema Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mysema.query.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.ExpressionBase;
|
||||
import com.mysema.query.types.FactoryExpression;
|
||||
import com.mysema.query.types.Visitor;
|
||||
|
||||
/**
|
||||
* EnumConversion ensures that the results of an enum projection confirm to the type of the
|
||||
* projection expression
|
||||
*
|
||||
* @author tiwe
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class EnumConversion<T> extends ExpressionBase<T> implements FactoryExpression<T> {
|
||||
|
||||
private static final long serialVersionUID = 7840412008633901748L;
|
||||
|
||||
private final List<Expression<?>> exprs;
|
||||
|
||||
private final Enum<?>[] values;
|
||||
|
||||
public EnumConversion(Expression<T> expr) {
|
||||
super(expr.getType());
|
||||
exprs = Collections.<Expression<?>>singletonList(expr);
|
||||
try {
|
||||
values = (Enum<?>[]) expr.getType().getMethod("values").invoke(null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(Visitor<R, C> v, C context) {
|
||||
return v.visit(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Expression<?>> getArgs() {
|
||||
return exprs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T newInstance(Object... args) {
|
||||
if (args[0] != null) {
|
||||
if (args[0] instanceof String) {
|
||||
return (T)Enum.valueOf((Class)getType(), (String)args[0]);
|
||||
} else if (args[0] instanceof Number) {
|
||||
return (T)values[((Number)args[0]).intValue()];
|
||||
} else {
|
||||
return (T)args[0];
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,7 +14,9 @@
|
||||
package com.mysema.query.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.ExpressionBase;
|
||||
import com.mysema.query.types.FactoryExpression;
|
||||
@ -35,6 +37,8 @@ public class NumberConversions<T> extends ExpressionBase<T> implements FactoryEx
|
||||
|
||||
private final FactoryExpression<T> expr;
|
||||
|
||||
private final Map<Class<?>, Enum<?>[]> values = Maps.newHashMap();
|
||||
|
||||
public NumberConversions(FactoryExpression<T> expr) {
|
||||
super(expr.getType());
|
||||
this.expr = expr;
|
||||
@ -50,11 +54,30 @@ public class NumberConversions<T> extends ExpressionBase<T> implements FactoryEx
|
||||
return expr.getArgs();
|
||||
}
|
||||
|
||||
private <E extends Enum<E>> Enum<E>[] getValues(Class<E> enumClass) {
|
||||
Enum<E>[] values = (Enum<E>[]) this.values.get(enumClass);
|
||||
if (values == null) {
|
||||
try {
|
||||
values = (Enum<E>[]) enumClass.getMethod("values").invoke(null);
|
||||
this.values.put(enumClass, values);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T newInstance(Object... args) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Class<?> type = expr.getArgs().get(i).getType();
|
||||
if (args[i] instanceof Number && !args[i].getClass().equals(type)) {
|
||||
if (Enum.class.isAssignableFrom(type) && !type.isInstance(args[i])) {
|
||||
if (args[i] instanceof String) {
|
||||
args[i] = Enum.valueOf((Class)type, (String)args[i]);
|
||||
} else if (args[i] instanceof Number) {
|
||||
args[i] = getValues((Class)type)[((Number)args[i]).intValue()];
|
||||
}
|
||||
} else if (args[i] instanceof Number && !type.isInstance(args[i])) {
|
||||
if (type.equals(Boolean.class)) {
|
||||
args[i] = ((Number)args[i]).intValue() > 0;
|
||||
} else if (Number.class.isAssignableFrom(type)){
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.mysema.query.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mysema.query.types.path.EnumPath;
|
||||
|
||||
public class EnumConversionTest {
|
||||
|
||||
public enum Color {GREEN, BLUE, RED, YELLOW, BLACK, WHITE}
|
||||
|
||||
@Test
|
||||
public void Name() {
|
||||
EnumPath<Color> color = new EnumPath<Color>(Color.class, "path");
|
||||
EnumConversion<Color> conv = new EnumConversion<Color>(color);
|
||||
assertEquals(Color.BLUE, conv.newInstance("BLUE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Ordinal() {
|
||||
EnumPath<Color> color = new EnumPath<Color>(Color.class, "path");
|
||||
EnumConversion<Color> conv = new EnumConversion<Color>(color);
|
||||
assertEquals(Color.RED, conv.newInstance(2));
|
||||
}
|
||||
}
|
||||
@ -7,11 +7,31 @@ import org.junit.Test;
|
||||
|
||||
import com.mysema.query.Tuple;
|
||||
import com.mysema.query.types.QTuple;
|
||||
import com.mysema.query.types.path.EnumPath;
|
||||
import com.mysema.query.types.path.NumberPath;
|
||||
import com.mysema.query.types.path.StringPath;
|
||||
|
||||
public class NumberConversionsTest {
|
||||
|
||||
|
||||
public enum Color {GREEN, BLUE, RED, YELLOW, BLACK, WHITE}
|
||||
|
||||
@Test
|
||||
public void Name() {
|
||||
EnumPath<Color> color = new EnumPath<Color>(Color.class, "path");
|
||||
QTuple qTuple = new QTuple(color);
|
||||
NumberConversions<Tuple> conversions = new NumberConversions<Tuple>(qTuple);
|
||||
assertEquals(Color.BLUE, conversions.newInstance("BLUE").get(color));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Ordinal() {
|
||||
EnumPath<Color> color = new EnumPath<Color>(Color.class, "path");
|
||||
QTuple qTuple = new QTuple(color);
|
||||
NumberConversions<Tuple> conversions = new NumberConversions<Tuple>(qTuple);
|
||||
assertEquals(Color.RED, conversions.newInstance(2).get(color));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Safe_Number_Conversion() {
|
||||
StringPath strPath = new StringPath("strPath");
|
||||
|
||||
@ -15,6 +15,7 @@ package com.mysema.query.jpa;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import com.mysema.query.support.EnumConversion;
|
||||
import com.mysema.query.support.NumberConversion;
|
||||
import com.mysema.query.support.NumberConversions;
|
||||
import com.mysema.query.types.Expression;
|
||||
@ -59,11 +60,15 @@ public final class Conversions {
|
||||
}
|
||||
} else if (Number.class.isAssignableFrom(expr.getType())) {
|
||||
return new NumberConversion<RT>(expr);
|
||||
} else if (Enum.class.isAssignableFrom(expr.getType())) {
|
||||
return new EnumConversion<RT>(expr);
|
||||
} else if (expr instanceof FactoryExpression) {
|
||||
FactoryExpression<RT> factorye = (FactoryExpression<RT>)expr;
|
||||
for (Expression<?> e : factorye.getArgs()) {
|
||||
if (Number.class.isAssignableFrom(e.getType())) {
|
||||
return new NumberConversions<RT>(factorye);
|
||||
} else if (Enum.class.isAssignableFrom(e.getType())) {
|
||||
return new NumberConversions<RT>(factorye);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +114,8 @@ public abstract class AbstractHibernateSQLQuery<Q extends AbstractHibernateSQLQu
|
||||
HibernateUtil.setConstants(query, constants, queryMixin.getMetadata().getParams());
|
||||
// set entity paths
|
||||
List<? extends Expression<?>> projection = queryMixin.getMetadata().getProjection();
|
||||
if (projection.get(0) instanceof EntityPath || projection.get(0).getType().isAnnotationPresent(Entity.class)) {
|
||||
if (!FactoryExpression.class.isAssignableFrom(projection.get(0).getClass()) &&
|
||||
(projection.get(0) instanceof EntityPath || projection.get(0).getType().isAnnotationPresent(Entity.class))) {
|
||||
if (projection.size() == 1) {
|
||||
Expression<?> expr = projection.get(0);
|
||||
if (expr instanceof Operation) {
|
||||
|
||||
@ -111,7 +111,8 @@ public abstract class AbstractJPASQLQuery<Q extends AbstractJPASQLQuery<Q> & com
|
||||
logQuery(queryString);
|
||||
List<? extends Expression<?>> projection = queryMixin.getMetadata().getProjection();
|
||||
Query query;
|
||||
if (projection.get(0) instanceof EntityPath || projection.get(0).getType().isAnnotationPresent(Entity.class)) {
|
||||
if (!FactoryExpression.class.isAssignableFrom(projection.get(0).getClass()) &&
|
||||
(projection.get(0) instanceof EntityPath || projection.get(0).getType().isAnnotationPresent(Entity.class))) {
|
||||
if (projection.size() == 1) {
|
||||
query = entityManager.createNativeQuery(queryString, projection.get(0).getType());
|
||||
} else {
|
||||
|
||||
@ -56,6 +56,7 @@ 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.Company.Rating;
|
||||
import com.mysema.query.jpa.domain.DomesticCat;
|
||||
@ -188,6 +189,7 @@ public abstract class AbstractJPATest {
|
||||
cat.setBirthdate(birthDate);
|
||||
cat.setDateField(date);
|
||||
cat.setTimeField(time);
|
||||
cat.setColor(Color.BLACK);
|
||||
save(cat);
|
||||
savedCats.add(cat);
|
||||
prev = cat;
|
||||
|
||||
@ -16,11 +16,13 @@ import org.junit.Test;
|
||||
|
||||
import com.mysema.query.jpa.AbstractSQLQuery;
|
||||
import com.mysema.query.jpa.domain.Cat;
|
||||
import com.mysema.query.jpa.domain.Color;
|
||||
import com.mysema.query.jpa.domain.QCat;
|
||||
import com.mysema.query.jpa.domain.sql.SAnimal;
|
||||
import com.mysema.query.sql.SQLSubQuery;
|
||||
import com.mysema.query.types.ConstructorExpression;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.Projections;
|
||||
import com.mysema.query.types.SubQueryExpression;
|
||||
import com.mysema.query.types.expr.DateExpression;
|
||||
import com.mysema.query.types.expr.Wildcard;
|
||||
@ -52,12 +54,20 @@ public abstract class AbstractSQLTest {
|
||||
assertEquals(6l, query().from(cat).where(cat.dtype.eq("C")).distinct().count());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Enum_Binding() {
|
||||
List<Cat> cats = query().from(cat)
|
||||
.list(Projections.bean(Cat.class, QCat.cat.color));
|
||||
assertFalse(cats.isEmpty());
|
||||
|
||||
for (Cat cat : cats) {
|
||||
assertEquals(Color.BLACK, cat.getColor());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void EntityProjections() {
|
||||
// not yet supported
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
|
||||
List<Cat> cats = query().from(cat).orderBy(cat.name.asc())
|
||||
.list(ConstructorExpression.create(Cat.class, cat.name, cat.id));
|
||||
assertEquals(6, cats.size());
|
||||
@ -68,7 +78,6 @@ public abstract class AbstractSQLTest {
|
||||
|
||||
@Test
|
||||
public void EntityQueries() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
SAnimal mate = new SAnimal("mate");
|
||||
QCat catEntity = QCat.cat;
|
||||
|
||||
@ -172,7 +181,6 @@ public abstract class AbstractSQLTest {
|
||||
|
||||
@Test
|
||||
public void Null_As_UniqueResult() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
assertNull(query().from(cat).where(cat.name.eq(UUID.randomUUID().toString()))
|
||||
.uniqueResult(cat.name));
|
||||
}
|
||||
@ -196,7 +204,6 @@ public abstract class AbstractSQLTest {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void Union() throws SQLException {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
SubQueryExpression<Integer> sq1 = sq().from(cat).unique(cat.id.max());
|
||||
SubQueryExpression<Integer> sq2 = sq().from(cat).unique(cat.id.min());
|
||||
List<Integer> list = query().union(sq1, sq2).list();
|
||||
@ -206,7 +213,6 @@ public abstract class AbstractSQLTest {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void Union_All() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
SubQueryExpression<Integer> sq1 = sq().from(cat).unique(cat.id.max());
|
||||
SubQueryExpression<Integer> sq2 = sq().from(cat).unique(cat.id.min());
|
||||
List<Integer> list = query().unionAll(sq1, sq2).list();
|
||||
@ -216,7 +222,6 @@ public abstract class AbstractSQLTest {
|
||||
@Test
|
||||
@ExcludeIn({Target.DERBY, Target.POSTGRES})
|
||||
public void Union2() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
List<Tuple> rows = query().union(
|
||||
new SQLSubQuery().from(cat).where(cat.name.eq("Beck")).distinct().list(cat.name, cat.id),
|
||||
new SQLSubQuery().from(cat).where(cat.name.eq("Kate")).distinct().list(cat.name, null))
|
||||
@ -231,7 +236,6 @@ public abstract class AbstractSQLTest {
|
||||
@Test
|
||||
@ExcludeIn(Target.DERBY)
|
||||
public void Union3() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
SAnimal cat2 = new SAnimal("cat2");
|
||||
List<Tuple> rows = query().union(
|
||||
new SQLSubQuery().from(cat).innerJoin(cat2).on(cat2.id.eq(cat.id)).list(cat.id, cat2.id),
|
||||
@ -259,7 +263,6 @@ public abstract class AbstractSQLTest {
|
||||
@Test
|
||||
@ExcludeIn({Target.DERBY, Target.ORACLE})
|
||||
public void Union5() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
SAnimal cat2 = new SAnimal("cat2");
|
||||
List<Tuple> rows = query().union(
|
||||
new SQLSubQuery().from(cat).join(cat2).on(cat2.id.eq(cat.id.add(1))).list(cat.id, cat2.id),
|
||||
@ -287,8 +290,6 @@ public abstract class AbstractSQLTest {
|
||||
@Test
|
||||
@ExcludeIn(Target.H2)
|
||||
public void Wildcard() {
|
||||
SAnimal cat = new SAnimal("cat");
|
||||
|
||||
List<Tuple> rows = query().from(cat).list(cat.all());
|
||||
assertEquals(6, rows.size());
|
||||
print(rows);
|
||||
|
||||
@ -24,6 +24,7 @@ import org.junit.rules.MethodRule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import com.mysema.query.jpa.domain.Cat;
|
||||
import com.mysema.query.jpa.domain.Color;
|
||||
import com.mysema.query.jpa.domain.QCat;
|
||||
import com.mysema.query.jpa.domain.sql.SAnimal;
|
||||
import com.mysema.query.jpa.hibernate.sql.HibernateSQLQuery;
|
||||
@ -55,12 +56,12 @@ public class HibernateSQLBase extends AbstractSQLTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
if (query().from(cat).notExists()) {
|
||||
session.save(new Cat("Beck",1));
|
||||
session.save(new Cat("Kate",2));
|
||||
session.save(new Cat("Kitty",3));
|
||||
session.save(new Cat("Bobby",4));
|
||||
session.save(new Cat("Harold",5));
|
||||
session.save(new Cat("Tim",6));
|
||||
session.save(new Cat("Beck", 1, Color.BLACK));
|
||||
session.save(new Cat("Kate", 2, Color.BLACK));
|
||||
session.save(new Cat("Kitty", 3, Color.BLACK));
|
||||
session.save(new Cat("Bobby", 4, Color.BLACK));
|
||||
session.save(new Cat("Harold", 5, Color.BLACK));
|
||||
session.save(new Cat("Tim", 6, Color.BLACK));
|
||||
session.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import org.junit.rules.MethodRule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import com.mysema.query.jpa.domain.Cat;
|
||||
import com.mysema.query.jpa.domain.Color;
|
||||
import com.mysema.query.jpa.domain.QCat;
|
||||
import com.mysema.query.jpa.domain.sql.SAnimal;
|
||||
import com.mysema.query.jpa.sql.JPASQLQuery;
|
||||
@ -58,12 +59,12 @@ public class JPASQLBase extends AbstractSQLTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
if (query().from(cat).notExists()) {
|
||||
entityManager.persist(new Cat("Beck", 1));
|
||||
entityManager.persist(new Cat("Kate", 2));
|
||||
entityManager.persist(new Cat("Kitty", 3));
|
||||
entityManager.persist(new Cat("Bobby", 4));
|
||||
entityManager.persist(new Cat("Harold", 5));
|
||||
entityManager.persist(new Cat("Tim", 6));
|
||||
entityManager.persist(new Cat("Beck", 1, Color.BLACK));
|
||||
entityManager.persist(new Cat("Kate", 2, Color.BLACK));
|
||||
entityManager.persist(new Cat("Kitty", 3, Color.BLACK));
|
||||
entityManager.persist(new Cat("Bobby", 4, Color.BLACK));
|
||||
entityManager.persist(new Cat("Harold", 5, Color.BLACK));
|
||||
entityManager.persist(new Cat("Tim", 6, Color.BLACK));
|
||||
entityManager.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +65,12 @@ public class Cat extends Animal {
|
||||
setName( name);
|
||||
}
|
||||
|
||||
public Cat(String name, int id, Color color) {
|
||||
setId(id);
|
||||
setName( name);
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
public Cat(String name, int id, List<Cat> k) {
|
||||
setId(id);
|
||||
setName( name);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user