#525769 : added basic JDO/SQL support

This commit is contained in:
Timo Westkämper 2010-07-18 14:50:05 +00:00
parent 9cc50f9b26
commit 2aaee440e8
16 changed files with 489 additions and 24 deletions

View File

@ -157,8 +157,28 @@
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</plugin>
<plugin>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>${project.version}</version>
<configuration>
<jdbcDriver>org.hsqldb.jdbcDriver</jdbcDriver>
<jdbcUrl>jdbc:hsqldb:target/jdo</jdbcUrl>
<packageName>com.mysema.query.jdoql.test.domain.sql</packageName>
<userName>sa</userName>
<targetFolder>src/test/java</targetFolder>
<namePrefix>S</namePrefix>
</configuration>
<dependencies>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.7</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -16,6 +16,9 @@ import javax.annotation.Nullable;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mysema.commons.lang.CloseableIterator;
import com.mysema.query.DefaultQueryMetadata;
import com.mysema.query.QueryException;
@ -39,6 +42,8 @@ import com.mysema.util.ResultIterator;
*
*/
public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements SQLCommonQuery<JDOSQLQuery>, Closeable{
private static final Logger logger = LoggerFactory.getLogger(JDOSQLQuery.class);
private final boolean detach;
@ -88,7 +93,10 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
serializer.serialize(queryMixin.getMetadata(), forCount);
// create Query
Query query = persistenceManager.newQuery(serializer.toString());
if (logger.isDebugEnabled()){
logger.debug(serializer.toString());
}
Query query = persistenceManager.newQuery("javax.jdo.query.SQL",serializer.toString());
orderedConstants = serializer.getConstants();
queries.add(query);
@ -100,6 +108,8 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
} else if (exprType.equals(EConstructor.class)){
query.setResultClass(projection.get(0).getType());
}
}else{
query.setResultClass(Long.class);
}
return query;
@ -164,7 +174,6 @@ public final class JDOSQLQuery extends AbstractSQLQuery<JDOSQLQuery> implements
queryMixin.addToProjection(expr);
Query countQuery = createQuery(true);
countQuery.setUnique(true);
countQuery.setResult("count(this)");
long total = (Long) execute(countQuery);
if (total > 0) {
QueryModifiers modifiers = queryMixin.getMetadata().getModifiers();

View File

@ -25,7 +25,7 @@ import com.mysema.query.types.path.PEntity;
public abstract class AbstractJDOTest {
private static final JDOQLTemplates templates = new JDOQLTemplates();
protected static PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("datanucleus.properties");
protected PersistenceManager pm;
@ -48,10 +48,6 @@ public abstract class AbstractJDOTest {
return query().from(source).where(condition).list(source);
}
// protected JDOQLUpdateClause update(PEntity<?> entity) {
// return new JDOQLUpdateClause(pm, entity, templates);
// }
protected JDOQLDeleteClause delete(PEntity<?> entity) {
return new JDOQLDeleteClause(pm, entity, templates);
}
@ -80,7 +76,6 @@ public abstract class AbstractJDOTest {
tx.begin();
pm.newQuery(Store.class).deletePersistentAll();
pm.newQuery(Product.class).deletePersistentAll();
tx.commit();
} finally {
if (tx.isActive()) {

View File

@ -0,0 +1,131 @@
package com.mysema.query.jdoql;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import org.junit.BeforeClass;
import org.junit.Test;
import com.mysema.query.SearchResults;
import com.mysema.query.jdoql.sql.JDOSQLQuery;
import com.mysema.query.jdoql.test.domain.sql.SProduct;
import com.mysema.query.jdoql.testdomain.Product;
import com.mysema.query.sql.HSQLDBTemplates;
import com.mysema.query.sql.SQLTemplates;
import com.mysema.query.types.EConstructor;
import com.mysema.query.types.expr.EBoolean;
public class JDOSQLQueryTest extends AbstractJDOTest{
private final SQLTemplates sqlTemplates = new HSQLDBTemplates();
private JDOSQLQuery sql(){
return new JDOSQLQuery(pm, sqlTemplates);
}
@Test
public void count(){
SProduct product = SProduct.product;
// total
assertEquals(30l, sql().from(product).count());
// startsWith
assertEquals(10l, sql().from(product).where(product.name.startsWith("A")).count());
assertEquals(10l, sql().from(product).where(product.name.startsWith("B")).count());
assertEquals(10l, sql().from(product).where(product.name.startsWith("C")).count());
// eq
for (int i = 0; i < 10; i++) {
assertEquals(1l, sql().from(product).where(product.name.eq("A"+i)).count());
assertEquals(1l, sql().from(product).where(product.name.eq("B"+i)).count());
assertEquals(1l, sql().from(product).where(product.name.eq("C"+i)).count());
}
}
@Test
public void scalarQueries(){
SProduct product = SProduct.product;
EBoolean filter = product.name.startsWith("A");
// count
assertEquals(10l, sql().from(product).where(filter).count());
// countDistinct
assertEquals(10l, sql().from(product).where(filter).countDistinct());
// list
assertEquals(10, sql().from(product).where(filter).list(product.name).size());
// list with limit
assertEquals(3, sql().from(product).limit(3).list(product.name).size());
// list with offset
// assertEquals(7, sql().from(product).offset(3).list(product.name).size());
// list with limit and offset
assertEquals(3, sql().from(product).offset(3).limit(3).list(product.name).size());
// list multiple
for (Object[] row : sql().from(product).list(product.productId, product.name, product.amount)){
assertNotNull(row[0]);
assertNotNull(row[1]);
assertNotNull(row[2]);
}
// listResults
SearchResults<String> results = sql().from(product).limit(3).listResults(product.name);
assertEquals(3, results.getResults().size());
assertEquals(30l, results.getTotal());
}
@Test
public void entityProjections(){
SProduct product = SProduct.product;
List<Product> products = sql()
.from(product)
.list(EConstructor.create(Product.class, product.name, product.description, product.price, product.amount));
assertEquals(30, products.size());
for (Product p : products){
assertNotNull(p.getName());
assertNotNull(p.getDescription());
assertNotNull(p.getPrice());
assertNotNull(p.getAmount());
}
}
@BeforeClass
public static void doPersist() {
// Persistence of a Product and a Book.
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
for (int i = 0; i < 10; i++) {
pm.makePersistent(new Product("C" + i, "F", 200.00, 2));
pm.makePersistent(new Product("B" + i, "E", 400.00, 4));
pm.makePersistent(new Product("A" + i, "D", 600.00, 6));
}
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
System.out.println("");
}
}

View File

@ -0,0 +1,55 @@
package com.mysema.query.jdoql.test.domain.sql;
import static com.mysema.query.types.path.PathMetadataFactory.forVariable;
import com.mysema.query.sql.ForeignKey;
import com.mysema.query.sql.PrimaryKey;
import com.mysema.query.sql.Table;
import com.mysema.query.types.Expr;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.path.PEntity;
import com.mysema.query.types.path.PNumber;
import com.mysema.query.types.path.PString;
/**
* SBook is a Querydsl query type for SBook
*/
@Table(value="BOOK")
public class SBook extends PEntity<SBook> {
private static final long serialVersionUID = -1566558053;
public static final SBook book = new SBook("BOOK");
public final PString author = createString("AUTHOR");
public final PNumber<Long> bookId = createNumber("BOOK_ID", Long.class);
public final PString isbn = createString("ISBN");
public final PString publisher = createString("PUBLISHER");
public final PrimaryKey<SBook> sysIdx65 = new PrimaryKey<SBook>(this, bookId);
public final ForeignKey<SProduct> bookFk1 = new ForeignKey<SProduct>(this, bookId, "PRODUCT_ID");
public SBook(String variable) {
super(SBook.class, forVariable(variable));
}
public SBook(PEntity<? extends SBook> entity) {
super(entity.getType(),entity.getMetadata());
}
public SBook(PathMetadata<?> metadata) {
super(SBook.class, metadata);
}
public Expr<Object[]> all() {
return CSimple.create(Object[].class, "{0}.*", this);
}
}

View File

@ -0,0 +1,70 @@
package com.mysema.query.jdoql.test.domain.sql;
import static com.mysema.query.types.path.PathMetadataFactory.forVariable;
import com.mysema.query.sql.ForeignKey;
import com.mysema.query.sql.PrimaryKey;
import com.mysema.query.sql.Table;
import com.mysema.query.types.Expr;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.path.PDate;
import com.mysema.query.types.path.PDateTime;
import com.mysema.query.types.path.PEntity;
import com.mysema.query.types.path.PNumber;
import com.mysema.query.types.path.PString;
import com.mysema.query.types.path.PTime;
/**
* SProduct is a Querydsl query type for SProduct
*/
@Table(value="PRODUCT")
public class SProduct extends PEntity<SProduct> {
private static final long serialVersionUID = -590374403;
public static final SProduct product = new SProduct("PRODUCT");
public final PNumber<Integer> amount = createNumber("AMOUNT", Integer.class);
public final PDate<java.sql.Date> datefield = createDate("DATEFIELD", java.sql.Date.class);
public final PString description = createString("DESCRIPTION");
public final PString name = createString("NAME");
public final PNumber<Double> price = createNumber("PRICE", Double.class);
public final PNumber<Long> productId = createNumber("PRODUCT_ID", Long.class);
public final PDateTime<java.util.Date> publicationdate = createDateTime("PUBLICATIONDATE", java.util.Date.class);
public final PTime<java.sql.Time> timefield = createTime("TIMEFIELD", java.sql.Time.class);
public final PrimaryKey<SProduct> sysIdx47 = new PrimaryKey<SProduct>(this, productId);
public final ForeignKey<SStoreProducts> _storeProductsFk2 = new ForeignKey<SStoreProducts>(this, productId, "PRODUCT_ID_EID");
public final ForeignKey<SBook> _bookFk1 = new ForeignKey<SBook>(this, productId, "BOOK_ID");
public final ForeignKey<SStoreProductsbyname> _storeProductsbynameFk2 = new ForeignKey<SStoreProductsbyname>(this, productId, "PRODUCT_ID_VID");
public SProduct(String variable) {
super(SProduct.class, forVariable(variable));
}
public SProduct(PEntity<? extends SProduct> entity) {
super(entity.getType(),entity.getMetadata());
}
public SProduct(PathMetadata<?> metadata) {
super(SProduct.class, metadata);
}
public Expr<Object[]> all() {
return CSimple.create(Object[].class, "{0}.*", this);
}
}

View File

@ -0,0 +1,53 @@
package com.mysema.query.jdoql.test.domain.sql;
import static com.mysema.query.types.path.PathMetadataFactory.forVariable;
import com.mysema.query.sql.ForeignKey;
import com.mysema.query.sql.PrimaryKey;
import com.mysema.query.sql.Table;
import com.mysema.query.types.Expr;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.path.PEntity;
import com.mysema.query.types.path.PNumber;
import com.mysema.query.types.path.PString;
/**
* SStore is a Querydsl query type for SStore
*/
@Table(value="STORE")
public class SStore extends PEntity<SStore> {
private static final long serialVersionUID = -1302810257;
public static final SStore store = new SStore("STORE");
public final PString name = createString("NAME");
public final PNumber<Long> storeId = createNumber("STORE_ID", Long.class);
public final PrimaryKey<SStore> sysIdx51 = new PrimaryKey<SStore>(this, storeId);
public final ForeignKey<SStoreProductsbyname> _storeProductsbynameFk1 = new ForeignKey<SStoreProductsbyname>(this, storeId, "STORE_ID_OID");
public final ForeignKey<SStoreProducts> _storeProductsFk1 = new ForeignKey<SStoreProducts>(this, storeId, "STORE_ID_OID");
public SStore(String variable) {
super(SStore.class, forVariable(variable));
}
public SStore(PEntity<? extends SStore> entity) {
super(entity.getType(),entity.getMetadata());
}
public SStore(PathMetadata<?> metadata) {
super(SStore.class, metadata);
}
public Expr<Object[]> all() {
return CSimple.create(Object[].class, "{0}.*", this);
}
}

View File

@ -0,0 +1,54 @@
package com.mysema.query.jdoql.test.domain.sql;
import static com.mysema.query.types.path.PathMetadataFactory.forVariable;
import com.mysema.query.sql.ForeignKey;
import com.mysema.query.sql.PrimaryKey;
import com.mysema.query.sql.Table;
import com.mysema.query.types.Expr;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.path.PEntity;
import com.mysema.query.types.path.PNumber;
/**
* SStoreProducts is a Querydsl query type for SStoreProducts
*/
@Table(value="STORE_PRODUCTS")
public class SStoreProducts extends PEntity<SStoreProducts> {
private static final long serialVersionUID = 1019873267;
public static final SStoreProducts storeProducts = new SStoreProducts("STORE_PRODUCTS");
public final PNumber<Integer> idx = createNumber("IDX", Integer.class);
public final PNumber<Long> productIdEid = createNumber("PRODUCT_ID_EID", Long.class);
public final PNumber<Long> storeIdOid = createNumber("STORE_ID_OID", Long.class);
public final PrimaryKey<SStoreProducts> sysIdx55 = new PrimaryKey<SStoreProducts>(this, idx, storeIdOid);
public final ForeignKey<SProduct> storeProductsFk2 = new ForeignKey<SProduct>(this, productIdEid, "PRODUCT_ID");
public final ForeignKey<SStore> storeProductsFk1 = new ForeignKey<SStore>(this, storeIdOid, "STORE_ID");
public SStoreProducts(String variable) {
super(SStoreProducts.class, forVariable(variable));
}
public SStoreProducts(PEntity<? extends SStoreProducts> entity) {
super(entity.getType(),entity.getMetadata());
}
public SStoreProducts(PathMetadata<?> metadata) {
super(SStoreProducts.class, metadata);
}
public Expr<Object[]> all() {
return CSimple.create(Object[].class, "{0}.*", this);
}
}

View File

@ -0,0 +1,55 @@
package com.mysema.query.jdoql.test.domain.sql;
import static com.mysema.query.types.path.PathMetadataFactory.forVariable;
import com.mysema.query.sql.ForeignKey;
import com.mysema.query.sql.PrimaryKey;
import com.mysema.query.sql.Table;
import com.mysema.query.types.Expr;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.path.PEntity;
import com.mysema.query.types.path.PNumber;
import com.mysema.query.types.path.PString;
/**
* SStoreProductsbyname is a Querydsl query type for SStoreProductsbyname
*/
@Table(value="STORE_PRODUCTSBYNAME")
public class SStoreProductsbyname extends PEntity<SStoreProductsbyname> {
private static final long serialVersionUID = 764053781;
public static final SStoreProductsbyname storeProductsbyname = new SStoreProductsbyname("STORE_PRODUCTSBYNAME");
public final PString key = createString("KEY");
public final PNumber<Long> productIdVid = createNumber("PRODUCT_ID_VID", Long.class);
public final PNumber<Long> storeIdOid = createNumber("STORE_ID_OID", Long.class);
public final PrimaryKey<SStoreProductsbyname> sysIdx53 = new PrimaryKey<SStoreProductsbyname>(this, key, storeIdOid);
public final ForeignKey<SStore> storeProductsbynameFk1 = new ForeignKey<SStore>(this, storeIdOid, "STORE_ID");
public final ForeignKey<SProduct> storeProductsbynameFk2 = new ForeignKey<SProduct>(this, productIdVid, "PRODUCT_ID");
public SStoreProductsbyname(String variable) {
super(SStoreProductsbyname.class, forVariable(variable));
}
public SStoreProductsbyname(PEntity<? extends SStoreProductsbyname> entity) {
super(entity.getType(),entity.getMetadata());
}
public SStoreProductsbyname(PathMetadata<?> metadata) {
super(SStoreProductsbyname.class, metadata);
}
public Expr<Object[]> all() {
return CSimple.create(Object[].class, "{0}.*", this);
}
}

View File

@ -8,4 +8,4 @@ log4j.appender.stdout.layout.ConversionPattern=%5p [%d{yyyy-MM-dd HH:mm:ss}] (%F
log4j.rootLogger=WARN, stdout
log4j.logger.com.mysema.query.jdoql=DEBUG, stdout
log4j.logger.com.mysema.query.jdoql=DEBUG, stdout

View File

@ -39,7 +39,14 @@
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-sql</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.2</version>
</dependency>
</dependencies>

View File

@ -23,7 +23,16 @@ import com.mysema.query.QueryFlag;
import com.mysema.query.QueryMetadata;
import com.mysema.query.QueryFlag.Position;
import com.mysema.query.serialization.SerializerBase;
import com.mysema.query.types.*;
import com.mysema.query.types.Constant;
import com.mysema.query.types.EConstructor;
import com.mysema.query.types.Expr;
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.Param;
import com.mysema.query.types.Path;
import com.mysema.query.types.SubQuery;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.expr.EBoolean;
import com.mysema.query.types.expr.ExprConst;
@ -98,15 +107,15 @@ public class SQLSerializer extends SerializerBase<SQLSerializer> {
return constants;
}
@SuppressWarnings("unchecked")
private List<Expr<?>> getIdentifierColumns(List<JoinExpression> joins) {
// TODO : get only identifier columns, maybe from @Table annotation
try {
List<Expr<?>> columns = new ArrayList<Expr<?>>();
for (JoinExpression j : joins) {
for (Field field : j.getTarget().getClass().getFields()) {
if (Expr.class.isAssignableFrom(field.getType())){
Expr<?> column = (Expr<?>) field.get(j.getTarget());
columns.add(column);
for (Field field : j.getTarget().getClass().getFields()) {
if (PrimaryKey.class.isAssignableFrom(field.getType())){
field.setAccessible(true);
columns.addAll(((PrimaryKey)field.get(j.getTarget())).getLocalColumns());
}
}
}
@ -173,8 +182,7 @@ public class SQLSerializer extends SerializerBase<SQLSerializer> {
}else{
append(templates.getDistinctCountStart());
if (sqlSelect.isEmpty()){
List<Expr<?>> columns = getIdentifierColumns(joins);
handle(columns.get(0));
handle(getIdentifierColumns(joins).get(0));
}else{
handle(COMMA, sqlSelect);
}

View File

@ -20,10 +20,11 @@ import com.mysema.query.types.path.PString;
import com.mysema.query.types.path.PTime;
import com.mysema.query.types.path.PathMetadataFactory;
@SuppressWarnings("all")
@Table("EMPLOYEE2")
public class QEmployee extends PEntity<QEmployee> {
private static final long serialVersionUID = 1394463749655231079L;
public Expr<Object[]> all(){
return CSimple.create(Object[].class, "{0}.*", this);
}

View File

@ -8,9 +8,10 @@ package com.mysema.query.sql.domain;
import com.mysema.query.types.EConstructor;
import com.mysema.query.types.Expr;
@SuppressWarnings("all")
public class QIdName extends EConstructor<IdName> {
private static final long serialVersionUID = 5770565824515003611L;
public QIdName(Expr<java.lang.Integer> id, Expr<java.lang.String> name) {
super(IdName.class, new Class[]{int.class, String.class}, id, name);
}

View File

@ -5,6 +5,7 @@
*/
package com.mysema.query.sql.domain;
import com.mysema.query.sql.PrimaryKey;
import com.mysema.query.sql.Table;
import com.mysema.query.types.Expr;
import com.mysema.query.types.PathMetadata;
@ -14,10 +15,12 @@ import com.mysema.query.types.path.PNumber;
import com.mysema.query.types.path.PString;
import com.mysema.query.types.path.PathMetadataFactory;
@SuppressWarnings("all")
@Table("SURVEY")
public class QSurvey extends PEntity<QSurvey> {
private static final long serialVersionUID = -7427577079709192842L;
public Expr<Object[]> all(){
return CSimple.create(Object[].class, "{0}.*", this);
}
@ -25,6 +28,8 @@ public class QSurvey extends PEntity<QSurvey> {
public final PString name = createString("NAME");
public final PNumber<java.lang.Integer> id = createNumber("ID", java.lang.Integer.class);
public final PrimaryKey<QSurvey> idKey = new PrimaryKey<QSurvey>(this,id);
public QSurvey(java.lang.String path) {
super(QSurvey.class, PathMetadataFactory.forVariable(path));

View File

@ -13,10 +13,11 @@ import com.mysema.query.types.path.PEntity;
import com.mysema.query.types.path.PString;
import com.mysema.query.types.path.PathMetadataFactory;
@SuppressWarnings("all")
@Table("TEST")
public class QTest_ extends PEntity<java.lang.Object> {
private static final long serialVersionUID = -8421112749591552595L;
public Expr<Object[]> all(){
return CSimple.create(Object[].class, "{0}.*", this);
}