mirror of
https://github.com/querydsl/querydsl.git
synced 2026-06-24 21:07:26 +08:00
improved JDO FactoryExpression handling
This commit is contained in:
parent
02caf656d2
commit
253273ce04
@ -16,8 +16,8 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<dn.version>2.1.2</dn.version>
|
||||
<dn.plugin.version>2.0.1</dn.plugin.version>
|
||||
<dn.version>3.2.0-m1</dn.version>
|
||||
<dn.plugin.version>3.2.0-m1</dn.plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -70,12 +70,18 @@
|
||||
</dependency>
|
||||
|
||||
<!-- test -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.datanucleus</groupId>
|
||||
<artifactId>datanucleus-core</artifactId>
|
||||
<version>${dn.version}</version>
|
||||
<scope>test</scope>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.datanucleus</groupId>
|
||||
<artifactId>datanucleus-api-jdo</artifactId>
|
||||
<version>${dn.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.datanucleus</groupId>
|
||||
<artifactId>datanucleus-core</artifactId>
|
||||
<version>${dn.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.datanucleus</groupId>
|
||||
@ -161,11 +167,11 @@
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.jdo</groupId>
|
||||
<artifactId>jdo2-api</artifactId>
|
||||
<version>2.3-ec</version>
|
||||
<scope>runtime</scope>
|
||||
<dependency>
|
||||
<groupId>org.datanucleus</groupId>
|
||||
<artifactId>datanucleus-api-jdo</artifactId>
|
||||
<version>${dn.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2011, 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
|
||||
@ -29,6 +29,7 @@ import javax.jdo.Query;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mysema.commons.lang.CloseableIterator;
|
||||
import com.mysema.commons.lang.IteratorAdapter;
|
||||
import com.mysema.query.DefaultQueryMetadata;
|
||||
@ -51,7 +52,7 @@ import com.mysema.query.types.QTuple;
|
||||
*
|
||||
* @param <Q>
|
||||
*/
|
||||
public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extends ProjectableQuery<Q>{
|
||||
public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extends ProjectableQuery<Q> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JDOQLQueryImpl.class);
|
||||
|
||||
@ -77,6 +78,9 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
|
||||
@Nullable
|
||||
protected Integer maxFetchDepth;
|
||||
|
||||
@Nullable
|
||||
private FactoryExpression<?> projection;
|
||||
|
||||
public AbstractJDOQLQuery(@Nullable PersistenceManager persistenceManager) {
|
||||
this(persistenceManager, JDOQLTemplates.DEFAULT, new DefaultQueryMetadata(), false);
|
||||
@ -111,7 +115,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
Query query = createQuery(true);
|
||||
query.setUnique(true);
|
||||
reset();
|
||||
Long rv = (Long) execute(query);
|
||||
Long rv = (Long) execute(query, true);
|
||||
if (rv != null) {
|
||||
return rv.longValue();
|
||||
} else {
|
||||
@ -129,7 +133,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
private Expression<?> getSource() {
|
||||
return queryMixin.getMetadata().getJoins().get(0).getTarget();
|
||||
}
|
||||
|
||||
|
||||
private Query createQuery(boolean forCount) {
|
||||
Expression<?> source = getSource();
|
||||
|
||||
@ -146,13 +150,9 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
|
||||
if (!forCount) {
|
||||
List<? extends Expression<?>> projection = queryMixin.getMetadata().getProjection();
|
||||
Class<?> exprType = projection.get(0).getClass();
|
||||
if (exprType.equals(QTuple.class)) {
|
||||
query.setResultClass(JDOTuple.class);
|
||||
} else if (FactoryExpression.class.isAssignableFrom(exprType)) {
|
||||
query.setResultClass(projection.get(0).getType());
|
||||
if (projection.get(0) instanceof FactoryExpression) {
|
||||
this.projection = (FactoryExpression<?>)projection.get(0);
|
||||
}
|
||||
|
||||
if (!fetchGroups.isEmpty()) {
|
||||
query.getFetchPlan().setGroups(fetchGroups);
|
||||
}
|
||||
@ -179,8 +179,18 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
}
|
||||
}
|
||||
|
||||
private Object project(FactoryExpression<?> expr, Object row) {
|
||||
if (row == null) {
|
||||
return null;
|
||||
} else if (row.getClass().isArray()) {
|
||||
return expr.newInstance((Object[])row);
|
||||
} else {
|
||||
return expr.newInstance(new Object[]{row});
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object execute(Query query) {
|
||||
private Object execute(Query query, boolean forCount) {
|
||||
Object rv;
|
||||
if (!orderedConstants.isEmpty()) {
|
||||
rv = query.executeWithArray(orderedConstants.toArray());
|
||||
@ -190,6 +200,18 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
if (isDetach()) {
|
||||
rv = detach(rv);
|
||||
}
|
||||
if (projection != null && !forCount) {
|
||||
if (rv instanceof List) {
|
||||
List<?> original = (List<?>)rv;
|
||||
rv = Lists.newArrayList();
|
||||
for (Object o : original) {
|
||||
((List)rv).add(project(projection, o));
|
||||
}
|
||||
} else {
|
||||
rv = project(projection, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -226,7 +248,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
@SuppressWarnings("unchecked")
|
||||
public <RT> List<RT> list(Expression<RT> expr) {
|
||||
queryMixin.addToProjection(expr);
|
||||
Object rv = execute(createQuery(false));
|
||||
Object rv = execute(createQuery(false), false);
|
||||
reset();
|
||||
return rv instanceof List ? (List<RT>)rv : Collections.singletonList((RT)rv);
|
||||
}
|
||||
@ -237,12 +259,12 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
Query countQuery = createQuery(true);
|
||||
countQuery.setUnique(true);
|
||||
countQuery.setResult("count(this)");
|
||||
long total = (Long) execute(countQuery);
|
||||
long total = (Long) execute(countQuery, true);
|
||||
if (total > 0) {
|
||||
QueryModifiers modifiers = queryMixin.getMetadata().getModifiers();
|
||||
Query query = createQuery(false);
|
||||
reset();
|
||||
return new SearchResults<RT>((List<RT>) execute(query), modifiers, total);
|
||||
return new SearchResults<RT>((List<RT>) execute(query, false), modifiers, total);
|
||||
} else {
|
||||
reset();
|
||||
return SearchResults.emptyResults();
|
||||
@ -271,6 +293,12 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Tuple uniqueResult(Expression<?>[] args) {
|
||||
return uniqueResult(new QTuple(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@ -278,14 +306,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
queryMixin.addToProjection(expr);
|
||||
return (RT)uniqueResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Tuple uniqueResult(Expression<?>[] args) {
|
||||
return uniqueResult(new QTuple(args));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private Object uniqueResult() {
|
||||
if (getMetadata().getModifiers().getLimit() == null) {
|
||||
@ -293,7 +314,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
|
||||
}
|
||||
Query query = createQuery(false);
|
||||
reset();
|
||||
Object rv = execute(query);
|
||||
Object rv = execute(query, false);
|
||||
if (rv instanceof List) {
|
||||
List<?> list = (List)rv;
|
||||
if (!list.isEmpty()) {
|
||||
|
||||
@ -27,6 +27,7 @@ import javax.jdo.Query;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mysema.commons.lang.CloseableIterator;
|
||||
import com.mysema.commons.lang.IteratorAdapter;
|
||||
import com.mysema.query.DefaultQueryMetadata;
|
||||
@ -36,12 +37,11 @@ import com.mysema.query.QueryMetadata;
|
||||
import com.mysema.query.QueryModifiers;
|
||||
import com.mysema.query.SearchResults;
|
||||
import com.mysema.query.Tuple;
|
||||
import com.mysema.query.jdo.JDOTuple;
|
||||
import com.mysema.query.sql.SQLCommonQuery;
|
||||
import com.mysema.query.sql.SQLSerializer;
|
||||
import com.mysema.query.sql.SQLTemplates;
|
||||
import com.mysema.query.types.ConstructorExpression;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.FactoryExpression;
|
||||
import com.mysema.query.types.QTuple;
|
||||
|
||||
/**
|
||||
@ -70,6 +70,10 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
private final PersistenceManager persistenceManager;
|
||||
|
||||
private List<Query> queries = new ArrayList<Query>(2);
|
||||
|
||||
@Nullable
|
||||
private FactoryExpression<?> projection;
|
||||
|
||||
|
||||
public JDOSQLQuery(@Nullable PersistenceManager persistenceManager, SQLTemplates templates) {
|
||||
this(persistenceManager, templates, new DefaultQueryMetadata(), false);
|
||||
@ -94,7 +98,7 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
Query query = createQuery(true);
|
||||
query.setUnique(true);
|
||||
reset();
|
||||
Long rv = (Long) execute(query);
|
||||
Long rv = (Long) execute(query, true);
|
||||
if (rv != null) {
|
||||
return rv.longValue();
|
||||
} else {
|
||||
@ -121,11 +125,8 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
|
||||
if (!forCount) {
|
||||
List<? extends Expression<?>> projection = queryMixin.getMetadata().getProjection();
|
||||
Class<?> exprType = projection.get(0).getClass();
|
||||
if (exprType.equals(QTuple.class)) {
|
||||
query.setResultClass(JDOTuple.class);
|
||||
} else if (ConstructorExpression.class.isAssignableFrom(exprType)) {
|
||||
query.setResultClass(projection.get(0).getType());
|
||||
if (projection.get(0) instanceof FactoryExpression) {
|
||||
this.projection = (FactoryExpression<?>)projection.get(0);
|
||||
}
|
||||
} else {
|
||||
query.setResultClass(Long.class);
|
||||
@ -142,8 +143,18 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
return persistenceManager.detachCopy(results);
|
||||
}
|
||||
}
|
||||
|
||||
private Object project(FactoryExpression<?> expr, Object row) {
|
||||
if (row == null) {
|
||||
return null;
|
||||
} else if (row.getClass().isArray()) {
|
||||
return expr.newInstance((Object[])row);
|
||||
} else {
|
||||
return expr.newInstance(new Object[]{row});
|
||||
}
|
||||
}
|
||||
|
||||
private Object execute(Query query) {
|
||||
private Object execute(Query query, boolean forCount) {
|
||||
Object rv;
|
||||
if (!orderedConstants.isEmpty()) {
|
||||
rv = query.executeWithArray(orderedConstants.toArray());
|
||||
@ -153,6 +164,17 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
if (isDetach()) {
|
||||
rv = detach(rv);
|
||||
}
|
||||
if (projection != null && !forCount) {
|
||||
if (rv instanceof List) {
|
||||
List<?> original = (List<?>)rv;
|
||||
rv = Lists.newArrayList();
|
||||
for (Object o : original) {
|
||||
((List)rv).add(project(projection, o));
|
||||
}
|
||||
} else {
|
||||
rv = project(projection, rv);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -180,7 +202,7 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
@SuppressWarnings("unchecked")
|
||||
public <RT> List<RT> list(Expression<RT> expr) {
|
||||
queryMixin.addToProjection(expr);
|
||||
Object rv = execute(createQuery(false));
|
||||
Object rv = execute(createQuery(false), false);
|
||||
reset();
|
||||
return rv instanceof List ? (List<RT>)rv : Collections.singletonList((RT)rv);
|
||||
}
|
||||
@ -190,12 +212,12 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
queryMixin.addToProjection(expr);
|
||||
Query countQuery = createQuery(true);
|
||||
countQuery.setUnique(true);
|
||||
long total = (Long) execute(countQuery);
|
||||
long total = (Long) execute(countQuery, true);
|
||||
if (total > 0) {
|
||||
QueryModifiers modifiers = queryMixin.getMetadata().getModifiers();
|
||||
Query query = createQuery(false);
|
||||
reset();
|
||||
return new SearchResults<RT>((List<RT>) execute(query), modifiers, total);
|
||||
return new SearchResults<RT>((List<RT>) execute(query, false), modifiers, total);
|
||||
} else {
|
||||
reset();
|
||||
return SearchResults.emptyResults();
|
||||
@ -239,7 +261,7 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
|
||||
}
|
||||
Query query = createQuery(false);
|
||||
reset();
|
||||
Object rv = execute(query);
|
||||
Object rv = execute(query, false);
|
||||
if (rv instanceof List) {
|
||||
List<?> list = (List<?>)rv;
|
||||
if (!list.isEmpty()) {
|
||||
|
||||
@ -178,12 +178,13 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void ConstructorProjection(){
|
||||
List<Projection> projections = query().from(store)
|
||||
List<Projection> results = query().from(store)
|
||||
.list(ConstructorExpression.create(Projection.class, store.name));
|
||||
assertFalse(projections.isEmpty());
|
||||
for (Projection projection : projections){
|
||||
assertNotNull(projection);
|
||||
assertFalse(results.isEmpty());
|
||||
for (Projection result : results){
|
||||
assertNotNull(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ public class FetchPlanTest extends AbstractJDOTest{
|
||||
.addFetchGroup("myfetchgroup2")
|
||||
.setMaxFetchDepth(2)
|
||||
.list(product);
|
||||
query.close();
|
||||
// query.close();
|
||||
|
||||
Field queriesField = AbstractJDOQLQuery.class.getDeclaredField("queries");
|
||||
queriesField.setAccessible(true);
|
||||
|
||||
@ -1,10 +1,4 @@
|
||||
javax.jdo.PersistenceManagerFactoryClass=org.datanucleus.jdo.JDOPersistenceManagerFactory
|
||||
|
||||
#javax.jdo.option.ConnectionDriverName=org.hsqldb.jdbcDriver
|
||||
#javax.jdo.option.ConnectionURL=jdbc:hsqldb:mem:nucleus1
|
||||
#javax.jdo.option.ConnectionUserName=sa
|
||||
#javax.jdo.option.ConnectionPassword=
|
||||
#javax.jdo.option.Mapping=hsql
|
||||
javax.jdo.PersistenceManagerFactoryClass=org.datanucleus.api.jdo.JDOPersistenceManagerFactory
|
||||
|
||||
javax.jdo.option.ConnectionDriverName=org.h2.Driver
|
||||
javax.jdo.option.ConnectionURL=jdbc:h2:target/test
|
||||
|
||||
@ -73,8 +73,9 @@ public abstract class AbstractJPAQuery<Q extends AbstractJPAQuery<Q>> extends JP
|
||||
|
||||
@Nullable
|
||||
protected FlushModeType flushMode;
|
||||
|
||||
protected boolean factoryExpressionUsed = false;
|
||||
|
||||
@Nullable
|
||||
protected FactoryExpression<?> projection;
|
||||
|
||||
public AbstractJPAQuery(EntityManager em) {
|
||||
this(em, JPAProvider.getTemplates(em), new DefaultQueryMetadata());
|
||||
@ -185,7 +186,7 @@ public abstract class AbstractJPAQuery<Q extends AbstractJPAQuery<Q>> extends JP
|
||||
}
|
||||
|
||||
} else {
|
||||
factoryExpressionUsed = true;
|
||||
this.projection = (FactoryExpression<?>)projection.get(0);
|
||||
if (wrapped != null) {
|
||||
getMetadata().clearProjection();
|
||||
getMetadata().addProjection(wrapped);
|
||||
@ -204,16 +205,15 @@ public abstract class AbstractJPAQuery<Q extends AbstractJPAQuery<Q>> extends JP
|
||||
*/
|
||||
private List<?> getResultList(Query query) {
|
||||
// TODO : use lazy list here?
|
||||
if (factoryExpressionUsed) {
|
||||
if (projection != null) {
|
||||
List<?> results = query.getResultList();
|
||||
List<Object> rv = new ArrayList<Object>(results.size());
|
||||
FactoryExpression<?> expr = (FactoryExpression<?>)getMetadata().getProjection().get(0);
|
||||
for (Object o : results) {
|
||||
if (o != null) {
|
||||
if (!o.getClass().isArray()) {
|
||||
o = new Object[]{o};
|
||||
}
|
||||
rv.add(expr.newInstance((Object[])o));
|
||||
rv.add(projection.newInstance((Object[])o));
|
||||
} else {
|
||||
rv.add(null);
|
||||
}
|
||||
@ -232,14 +232,13 @@ public abstract class AbstractJPAQuery<Q extends AbstractJPAQuery<Q>> extends JP
|
||||
*/
|
||||
@Nullable
|
||||
private Object getSingleResult(Query query) {
|
||||
if (factoryExpressionUsed) {
|
||||
if (projection != null) {
|
||||
Object result = query.getSingleResult();
|
||||
FactoryExpression<?> expr = (FactoryExpression<?>)getMetadata().getProjection().get(0);
|
||||
if (result != null) {
|
||||
if (!result.getClass().isArray()) {
|
||||
result = new Object[]{result};
|
||||
}
|
||||
return expr.newInstance((Object[])result);
|
||||
return projection.newInstance((Object[])result);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ public final class JPAQuery extends AbstractJPAQuery<JPAQuery> implements JPQLQu
|
||||
*/
|
||||
public JPAQuery clone(EntityManager entityManager) {
|
||||
JPAQuery q = new JPAQuery(entityManager, JPAProvider.getTemplates(entityManager), getMetadata().clone());
|
||||
q.factoryExpressionUsed = factoryExpressionUsed;
|
||||
q.projection = projection;
|
||||
q.flushMode = flushMode;
|
||||
q.hints.putAll(hints);
|
||||
q.lockMode = lockMode;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user