mirror of https://github.com/apache/openjpa.git
OPENJPA-1191 :
Add Tuple implementation and unit tests. Also added some basic typed result and multiselect testscases git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@796773 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c47bd9ee3a
commit
49f000f54a
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="CRIT_RES_ITEM")
|
||||||
|
public class Item {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Order order;
|
||||||
|
|
||||||
|
@OneToOne(cascade=CascadeType.PERSIST)
|
||||||
|
private Producer producer;
|
||||||
|
|
||||||
|
public Producer getProduct() {
|
||||||
|
return producer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProduct(Producer product) {
|
||||||
|
this.producer = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
import javax.persistence.metamodel.StaticMetamodel;
|
||||||
|
|
||||||
|
@StaticMetamodel(value=Item.class)
|
||||||
|
public class Item_ {
|
||||||
|
public static volatile SingularAttribute<Item, Order> order;
|
||||||
|
public static volatile SingularAttribute<Item, Producer> producer;
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="CRIT_RES_ORD")
|
||||||
|
public class Order {
|
||||||
|
@Id
|
||||||
|
long id;
|
||||||
|
boolean filled;
|
||||||
|
Date date;
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.PERSIST)
|
||||||
|
Set<Item> items;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
Shop shop;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFilled() {
|
||||||
|
return filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilled(boolean filled) {
|
||||||
|
this.filled = filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Item> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(Set<Item> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shop getShop() {
|
||||||
|
return shop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShop(Shop shop) {
|
||||||
|
this.shop = shop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toPrettyString() {
|
||||||
|
return String.format("Order: %s date=%s filled=%s",getId(), getDate(), isFilled());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
public class OrderProducer {
|
||||||
|
|
||||||
|
private Order order;
|
||||||
|
private Producer producer;
|
||||||
|
|
||||||
|
public OrderProducer(Order o, Producer p) {
|
||||||
|
order = o;
|
||||||
|
producer = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return order.toPrettyString() + " " + producer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Producer getProducer() {
|
||||||
|
return producer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProduct(Producer producer) {
|
||||||
|
this.producer = producer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.metamodel.SetAttribute;
|
||||||
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
import javax.persistence.metamodel.StaticMetamodel;
|
||||||
|
|
||||||
|
@StaticMetamodel(value = Order.class)
|
||||||
|
public class Order_ {
|
||||||
|
public static volatile SetAttribute<Order, Item> items;
|
||||||
|
public static volatile SingularAttribute<Order, Boolean> filled;
|
||||||
|
public static volatile SingularAttribute<Order, Date> date;
|
||||||
|
public static volatile SingularAttribute<Order, Shop> shop;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Producer {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(Item item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import javax.persistence.metamodel.StaticMetamodel;
|
||||||
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
|
@StaticMetamodel(value=Producer.class)
|
||||||
|
public class Producer_ {
|
||||||
|
public static volatile SingularAttribute<Producer, Item> item;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="CRIT_RES_SHOP")
|
||||||
|
public class Shop {
|
||||||
|
@Id
|
||||||
|
long id;
|
||||||
|
|
||||||
|
String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.PERSIST)
|
||||||
|
Set<Order> orders;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Order> getOrders() {
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrders(Set<Order> orders) {
|
||||||
|
this.orders = orders;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import javax.persistence.metamodel.SetAttribute;
|
||||||
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
import javax.persistence.metamodel.StaticMetamodel;
|
||||||
|
|
||||||
|
@StaticMetamodel(value=Shop.class)
|
||||||
|
public class Shop_ {
|
||||||
|
public static volatile SingularAttribute<Shop, String> name;
|
||||||
|
public static volatile SetAttribute<Shop, Order>orders;
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence.criteria.results;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Join;
|
||||||
|
import javax.persistence.criteria.QueryBuilder;
|
||||||
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
|
||||||
|
public class TestTypedResults extends SingleEMFTestCase {
|
||||||
|
|
||||||
|
private static final int N_ORDERS = 15;
|
||||||
|
private static final int N_ITEMS_PER_ORDER = 3;
|
||||||
|
|
||||||
|
// use short data format
|
||||||
|
private static final String[] ORDER_DATES =
|
||||||
|
{ "3/12/2008 1:00 PM", "10/01/2008 1:51 AM", "12/12/2008 10:01 AM", "5/21/2009 3:23 PM" };
|
||||||
|
|
||||||
|
DateFormat df = DateFormat.getInstance(); // uses SHORT dateformat by default
|
||||||
|
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
setUp(Order.class, Item.class, Shop.class, Producer.class);
|
||||||
|
populate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void populate() throws ParseException {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
Shop s = new Shop();
|
||||||
|
Order order;
|
||||||
|
Item item;
|
||||||
|
Producer p;
|
||||||
|
|
||||||
|
s.setId(1);
|
||||||
|
s.setName("eBay.com");
|
||||||
|
s.setOrders(new HashSet<Order>());
|
||||||
|
|
||||||
|
for (int i = 1; i <= N_ORDERS; i++) {
|
||||||
|
order = new Order();
|
||||||
|
order.setId(i);
|
||||||
|
order.setDate(df.parse(ORDER_DATES[i % ORDER_DATES.length]));
|
||||||
|
order.setFilled(i % 2 == 0 ? true : false);
|
||||||
|
order.setShop(s);
|
||||||
|
order.setItems(new HashSet<Item>());
|
||||||
|
s.getOrders().add(order);
|
||||||
|
for (int j = 1; j <= N_ITEMS_PER_ORDER; j++) {
|
||||||
|
item = new Item();
|
||||||
|
item.setOrder(order);
|
||||||
|
order.getItems().add(item);
|
||||||
|
p = new Producer();
|
||||||
|
p.setName("filler");
|
||||||
|
p.setItem(item);
|
||||||
|
item.setProduct(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
em.persist(s);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that a query using a date field works the same with JPQL, JPQL (typed), Criteria (typed), and via a
|
||||||
|
* NativeQuery
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testTypedJPQLQuery() {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
Query jpqlQuery = em.createQuery("Select o from Order o where o.filled = true");
|
||||||
|
// Don't suppress warnings.
|
||||||
|
List<Order> jpqlResults = jpqlQuery.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, jpqlResults.size());
|
||||||
|
|
||||||
|
TypedQuery<Order> jpqlTypedQuery = em.createQuery("Select o from Order o where o.filled = true", Order.class);
|
||||||
|
List<Order> jpqlTypedResults = jpqlTypedQuery.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, jpqlTypedResults.size());
|
||||||
|
|
||||||
|
// create the same query and get typed results.
|
||||||
|
QueryBuilder qb = em.getQueryBuilder();
|
||||||
|
CriteriaQuery<Order> cq = qb.createQuery(Order.class);
|
||||||
|
Root<Order> order = cq.from(Order.class);
|
||||||
|
cq.select(order).where(qb.equal(order.get(Order_.filled), Boolean.TRUE));
|
||||||
|
|
||||||
|
TypedQuery<Order> typedCriteriaQuery = em.createQuery(cq);
|
||||||
|
List<Order> typedCriteriaResults = typedCriteriaQuery.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, typedCriteriaResults.size());
|
||||||
|
|
||||||
|
Query nativeQ = em.createNativeQuery("SELECT * FROM CRIT_RES_ORD o WHERE (o.filled = 1)", Order.class);
|
||||||
|
// Don't suppress warnings.
|
||||||
|
List<Order> typedNativeResults = nativeQ.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, typedNativeResults.size());
|
||||||
|
|
||||||
|
for (Order o : jpqlResults) {
|
||||||
|
assertTrue(jpqlTypedResults.contains(o));
|
||||||
|
assertTrue(typedCriteriaResults.contains(o));
|
||||||
|
assertTrue(typedNativeResults.contains(o));
|
||||||
|
}
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that a query using a date field works the same with JPQL, JPQL (typed), Criteria (typed), and via a
|
||||||
|
* NativeQuery
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testDateQuery() throws Exception {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
Query jpqlQuery = em.createQuery("Select o from Order o where o.date < :maxDate");
|
||||||
|
jpqlQuery.setParameter("maxDate", df.parse(ORDER_DATES[2]));
|
||||||
|
List<Order> jpqlResults = jpqlQuery.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, jpqlResults.size());
|
||||||
|
|
||||||
|
TypedQuery<Order> typedJpqlQuery = em.createQuery("Select o from Order o where o.date < :maxDate", Order.class);
|
||||||
|
typedJpqlQuery.setParameter("maxDate", df.parse(ORDER_DATES[2]));
|
||||||
|
List<Order> typedJpqlResults = typedJpqlQuery.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, typedJpqlResults.size());
|
||||||
|
|
||||||
|
QueryBuilder qb = em.getQueryBuilder();
|
||||||
|
CriteriaQuery<Order> criteriaQuery = qb.createQuery(Order.class);
|
||||||
|
Root<Order> order = criteriaQuery.from(Order.class);
|
||||||
|
criteriaQuery.select(order).where(qb.lessThan(order.get(Order_.date), df.parse(ORDER_DATES[2])));
|
||||||
|
TypedQuery<Order> tq = em.createQuery(criteriaQuery);
|
||||||
|
List<Order> criteriaResults = tq.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, criteriaResults.size());
|
||||||
|
|
||||||
|
String parm = new java.sql.Timestamp(df.parse(ORDER_DATES[2]).getTime()).toString();
|
||||||
|
Query nativeQuery =
|
||||||
|
em.createNativeQuery("Select * from CRIT_RES_ORD o WHERE (o.date < '" + parm + "')", Order.class);
|
||||||
|
List<Order> nativeResults = nativeQuery.getResultList();
|
||||||
|
assertEquals(N_ORDERS / 2, nativeResults.size());
|
||||||
|
|
||||||
|
for (Order o : jpqlResults) {
|
||||||
|
assertTrue(typedJpqlResults.contains(o));
|
||||||
|
assertTrue(criteriaResults.contains(o));
|
||||||
|
assertTrue(nativeResults.contains(o));
|
||||||
|
}
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testcase to verify that selecting multiple results in a variety of ways returns the same results. Results are
|
||||||
|
* returned via a normal Object [] (JPQL), Tuple (Criteria), and a custom tuple (Criteria.construct)
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testMultiSelect() throws Exception {
|
||||||
|
// get results from traditional JPQL
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
Query jpqlQuery =
|
||||||
|
em.createQuery("SELECT o, p from Order o JOIN o.items i JOIN i.producer p WHERE o.filled = true");
|
||||||
|
// don't suppress warnings.
|
||||||
|
List<Object[]> jpqlResults = jpqlQuery.getResultList();
|
||||||
|
|
||||||
|
// Get results using Tuple
|
||||||
|
QueryBuilder qb = em.getQueryBuilder();
|
||||||
|
CriteriaQuery<Tuple> criteriaQuery = qb.createTupleQuery();
|
||||||
|
Root<Order> order = criteriaQuery.from(Order.class);
|
||||||
|
Join<Item, Producer> producer = order.join(Order_.items).join(Item_.producer);
|
||||||
|
criteriaQuery.select(qb.tuple(order, producer));
|
||||||
|
criteriaQuery.where(qb.equal(order.get(Order_.filled), Boolean.TRUE));
|
||||||
|
TypedQuery<Tuple> eq = em.createQuery(criteriaQuery);
|
||||||
|
List<Tuple> criteriaResults = eq.getResultList();
|
||||||
|
|
||||||
|
// Get results using custom class
|
||||||
|
CriteriaQuery<OrderProducer> constructQuery = qb.createQuery(OrderProducer.class);
|
||||||
|
Root<Order> order2 = constructQuery.from(Order.class);
|
||||||
|
Join<Item, Producer> producer2 = order.join(Order_.items).join(Item_.producer);
|
||||||
|
constructQuery.select(qb.construct(OrderProducer.class, order2, producer2));
|
||||||
|
constructQuery.where(qb.equal(order2.get(Order_.filled), Boolean.TRUE));
|
||||||
|
TypedQuery<OrderProducer> typedQuery = em.createQuery(constructQuery);
|
||||||
|
List<OrderProducer> constructResults = typedQuery.getResultList();
|
||||||
|
|
||||||
|
assertEquals(N_ORDERS / 2 * N_ITEMS_PER_ORDER, jpqlResults.size());
|
||||||
|
assertEquals(N_ORDERS / 2 * N_ITEMS_PER_ORDER, criteriaResults.size());
|
||||||
|
assertEquals(N_ORDERS / 2 * N_ITEMS_PER_ORDER, constructResults.size());
|
||||||
|
|
||||||
|
for (Object[] os : jpqlResults) {
|
||||||
|
assertEquals(2, os.length);
|
||||||
|
assertTrue(os[0] instanceof Order);
|
||||||
|
assertTrue(os[1] instanceof Producer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cheap way to ensure that we have the same contents.
|
||||||
|
// if needed an orderBy clause can be added to make this more robust.
|
||||||
|
Object[] jpqlTuple;
|
||||||
|
Tuple criteriaTuple;
|
||||||
|
OrderProducer constructTuple;
|
||||||
|
for (int i = 0; i < jpqlResults.size(); i++) {
|
||||||
|
jpqlTuple = jpqlResults.get(i);
|
||||||
|
criteriaTuple = criteriaResults.get(i);
|
||||||
|
constructTuple = constructResults.get(i);
|
||||||
|
assertEquals(jpqlTuple[0], criteriaTuple.get(0));
|
||||||
|
assertEquals(jpqlTuple[1], criteriaTuple.get(1));
|
||||||
|
assertEquals(jpqlTuple[0], constructTuple.getOrder());
|
||||||
|
assertEquals(jpqlTuple[1], constructTuple.getProducer());
|
||||||
|
}
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -945,7 +945,8 @@ public class EntityManagerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> TypedQuery<T> createQuery(String query, Class<T> resultClass) {
|
public <T> TypedQuery<T> createQuery(String query, Class<T> resultClass) {
|
||||||
throw new UnsupportedOperationException();
|
return new QueryImpl(this, _ret,
|
||||||
|
_broker.newQuery(JPQLParser.LANG_JPQL, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenJPAQuery createQuery(String query) {
|
public OpenJPAQuery createQuery(String query) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.openjpa.persistence;
|
package org.apache.openjpa.persistence;
|
||||||
|
|
||||||
import javax.persistence.TupleElement;
|
import javax.persistence.TupleElement;
|
||||||
|
@ -30,6 +31,7 @@ import javax.persistence.TupleElement;
|
||||||
public class TupleElementImpl<X> implements TupleElement<X> {
|
public class TupleElementImpl<X> implements TupleElement<X> {
|
||||||
private String _alias;
|
private String _alias;
|
||||||
protected final Class<X> _cls;
|
protected final Class<X> _cls;
|
||||||
|
private X _value;
|
||||||
|
|
||||||
protected TupleElementImpl(Class<X> cls) {
|
protected TupleElementImpl(Class<X> cls) {
|
||||||
_cls = cls;
|
_cls = cls;
|
||||||
|
@ -46,4 +48,15 @@ public class TupleElementImpl<X> implements TupleElement<X> {
|
||||||
public Class<X> getJavaType() {
|
public Class<X> getJavaType() {
|
||||||
return _cls;
|
return _cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public X getValue() {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void setValue(Object x) {
|
||||||
|
// X is unknown at compile time in TupleImpl when we construct a new Tuple.
|
||||||
|
// so we're stuck with this ugly cast.
|
||||||
|
_value = (X) x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import javax.persistence.TupleElement;
|
||||||
|
|
||||||
|
public class TupleImpl implements Tuple {
|
||||||
|
List<TupleElement<?>> elements = new ArrayList<TupleElement<?>>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the specified tuple element.
|
||||||
|
*
|
||||||
|
* @param tupleElement
|
||||||
|
* tuple element
|
||||||
|
* @return value of tuple element
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if tuple element does not correspond to an element in the query result tuple
|
||||||
|
*/
|
||||||
|
public <X> X get(TupleElement<X> tupleElement) {
|
||||||
|
if (!elements.contains(tupleElement)) {
|
||||||
|
throw new IllegalArgumentException("tupleElement was not found in this tuple"); // TODO MDD improve
|
||||||
|
}
|
||||||
|
|
||||||
|
TupleElementImpl<X> impl = (TupleElementImpl<X>) tupleElement;
|
||||||
|
return impl.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the tuple element to which the specified alias has been assigned.
|
||||||
|
*
|
||||||
|
* @param alias
|
||||||
|
* alias assigned to tuple element
|
||||||
|
* @param type
|
||||||
|
* of the tuple element
|
||||||
|
* @return value of the tuple element
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if alias does not correspond to an element in the query result tuple or element cannot be assigned to
|
||||||
|
* the specified type
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <X> X get(String alias, Class<X> type) {
|
||||||
|
if (type == null) {
|
||||||
|
throw new IllegalArgumentException("Type was null");
|
||||||
|
}
|
||||||
|
Object rval = get(alias);
|
||||||
|
if (!type.isAssignableFrom(rval.getClass())) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"TupleElement type did not match for alias: %s. Provided type: %s actual type: %s", alias, type, rval
|
||||||
|
.getClass().toString()));
|
||||||
|
}
|
||||||
|
return (X) rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the tuple element to which the specified alias has been assigned.
|
||||||
|
*
|
||||||
|
* @param alias
|
||||||
|
* alias assigned to tuple element
|
||||||
|
* @return value of the tuple element
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if alias does not correspond to an element in the query result tuple
|
||||||
|
*/
|
||||||
|
public Object get(String alias) {
|
||||||
|
if (alias == null) {
|
||||||
|
throw new IllegalArgumentException(String.format("Alias was null."));
|
||||||
|
}
|
||||||
|
for (TupleElement<?> te : elements) {
|
||||||
|
if (alias.equals(te.getAlias())) {
|
||||||
|
return ((TupleElementImpl<?>) te).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(String.format("Alias %s was not found.", alias));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the element at the specified position in the result tuple. The first position is 0.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* position in result tuple
|
||||||
|
* @param type
|
||||||
|
* type of the tuple element
|
||||||
|
* @return value of the tuple element
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if i exceeds length of result tuple or element cannot be assigned to the specified type
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <X> X get(int i, Class<X> type) {
|
||||||
|
if (type == null) {
|
||||||
|
throw new IllegalArgumentException("Type was null");
|
||||||
|
}
|
||||||
|
Object rval = get(i);
|
||||||
|
if(! type.isAssignableFrom(rval.getClass())) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"Type did not match for position: %d. Provided type: %s actual type: %s", i, type.getClass(),
|
||||||
|
rval.getClass()));
|
||||||
|
}
|
||||||
|
return (X) rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the element at the specified position in the result tuple. The first position is 0.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* position in result tuple
|
||||||
|
* @return value of the tuple element
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if i exceeds length of result tuple
|
||||||
|
*/
|
||||||
|
public Object get(int i) {
|
||||||
|
if (i > elements.size()) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"Attempt to read TupleElement %d when there are only %d elements available", i, elements.size()));
|
||||||
|
}
|
||||||
|
if (i == -1) {
|
||||||
|
throw new IllegalArgumentException("Cannot obtain the -1th element in this tuple. Thank you for playing");
|
||||||
|
}
|
||||||
|
return toArray()[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the values of the result tuple elements as an array.
|
||||||
|
*
|
||||||
|
* @return tuple element values
|
||||||
|
*/
|
||||||
|
public Object[] toArray() {
|
||||||
|
Object[] rval = new Object[elements.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (TupleElement<?> tupleElement : elements) {
|
||||||
|
rval[i] = ((TupleElementImpl<?>) tupleElement).getValue();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the tuple elements
|
||||||
|
*
|
||||||
|
* @return tuple elements
|
||||||
|
*/
|
||||||
|
public List<TupleElement<?>> getElements() {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void put(Object key, Object value) {
|
||||||
|
// TODO check for duplicate aliases?
|
||||||
|
TupleElementImpl<?> element = new TupleElementImpl(value.getClass());
|
||||||
|
element.setAlias((String) key);
|
||||||
|
element.setValue(value);
|
||||||
|
elements.add(element);
|
||||||
|
}
|
||||||
|
}
|
|
@ -678,8 +678,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser {
|
||||||
return new Expressions.IsNull((ExpressionImpl<?> )x);
|
return new Expressions.IsNull((ExpressionImpl<?> )x);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundSelection<Tuple> tuple(Selection<?>... arg0) {
|
public CompoundSelection<Tuple> tuple(Selection<?>... selections) {
|
||||||
// TODO Auto-generated method stub
|
return new TupleSelection<Tuple>(Tuple.class, selections);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.openjpa.kernel.exps.ExpressionFactory;
|
||||||
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||||
import org.apache.openjpa.kernel.exps.Value;
|
import org.apache.openjpa.kernel.exps.Value;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
|
import org.apache.openjpa.persistence.TupleImpl;
|
||||||
import org.apache.openjpa.persistence.meta.AbstractManagedType;
|
import org.apache.openjpa.persistence.meta.AbstractManagedType;
|
||||||
import org.apache.openjpa.persistence.meta.Members;
|
import org.apache.openjpa.persistence.meta.Members;
|
||||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||||
|
@ -242,7 +243,12 @@ public class CriteriaExpressionBuilder {
|
||||||
ExpressionFactory factory, CriteriaQueryImpl<?> q, MetamodelImpl model,
|
ExpressionFactory factory, CriteriaQueryImpl<?> q, MetamodelImpl model,
|
||||||
Map<Expression<?>, Value> exp2Vals) {
|
Map<Expression<?>, Value> exp2Vals) {
|
||||||
for (Selection<?> s : selections) {
|
for (Selection<?> s : selections) {
|
||||||
if (s instanceof NewInstanceSelection<?>) {
|
if(s instanceof TupleSelection<?> ) {
|
||||||
|
exps.resultClass = TupleImpl.class;
|
||||||
|
getProjections(exps, ((TupleSelection<?>)s).getSelectionItems(), projections, aliases,
|
||||||
|
clauses, factory, q, model, exp2Vals);
|
||||||
|
}
|
||||||
|
else if (s instanceof NewInstanceSelection<?>) {
|
||||||
exps.resultClass = s.getJavaType();
|
exps.resultClass = s.getJavaType();
|
||||||
getProjections(exps, ((NewInstanceSelection<?>)s).getSelectionItems(), projections, aliases,
|
getProjections(exps, ((NewInstanceSelection<?>)s).getSelectionItems(), projections, aliases,
|
||||||
clauses, factory, q, model, exp2Vals);
|
clauses, factory, q, model, exp2Vals);
|
||||||
|
|
|
@ -24,8 +24,6 @@ import java.util.List;
|
||||||
import javax.persistence.criteria.CompoundSelection;
|
import javax.persistence.criteria.CompoundSelection;
|
||||||
import javax.persistence.criteria.Selection;
|
import javax.persistence.criteria.Selection;
|
||||||
|
|
||||||
import org.apache.openjpa.persistence.TupleElementImpl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A selection item that constructs new instance of a user-defined class with arguments specified as other selected
|
* A selection item that constructs new instance of a user-defined class with arguments specified as other selected
|
||||||
* items.
|
* items.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.apache.openjpa.persistence.criteria;
|
||||||
|
|
||||||
|
import javax.persistence.criteria.Selection;
|
||||||
|
|
||||||
|
public class TupleSelection<Tuple> extends NewInstanceSelection<Tuple> {
|
||||||
|
|
||||||
|
public TupleSelection(final Class<Tuple> cls, final Selection<?>[] selections) {
|
||||||
|
super(cls, selections);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,269 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.openjpa.persistence;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import javax.persistence.TupleElement;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the following methods in TupleImpl
|
||||||
|
* <ul>
|
||||||
|
* <li>Tuple</li>
|
||||||
|
* <ul>
|
||||||
|
* <li>get(int)</li>
|
||||||
|
* <li>get(int, Class<X>)</li>
|
||||||
|
* <li>get(String)</li>
|
||||||
|
* <li>get(String, Class<X>)</li>
|
||||||
|
* <li>get(TupleElement<X>)</li>
|
||||||
|
* <li>getElements()</li>
|
||||||
|
* <li>toArray()</li>
|
||||||
|
* </ul>
|
||||||
|
* <li>TupleImpl</li>
|
||||||
|
* <ul>
|
||||||
|
* <li>get(Object)</li>
|
||||||
|
* <li>getValues()</li>
|
||||||
|
* <li>put(Object, Object)</li>
|
||||||
|
* </ul>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class TestTupleImpl extends TestCase {
|
||||||
|
protected Order _order = new Order();
|
||||||
|
protected Product _product = new Product();
|
||||||
|
protected Item _item = new Item();
|
||||||
|
protected Store _store = new Store();
|
||||||
|
protected UrgentOrder _urgentOrder = new UrgentOrder();
|
||||||
|
protected Tuple tuple = getTuple();
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default tuple with some arbitrary pseudo entities
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected TupleImpl getTuple() {
|
||||||
|
TupleImpl tuple = new TupleImpl();
|
||||||
|
tuple.put("alias1", _order);
|
||||||
|
tuple.put("alias2", _product);
|
||||||
|
tuple.put("alias3", _item);
|
||||||
|
tuple.put("alias4", _store);
|
||||||
|
tuple.put("alias5", _urgentOrder);
|
||||||
|
return tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetInt() {
|
||||||
|
assertEquals(_order, tuple.get(0));
|
||||||
|
assertEquals(_product, tuple.get(1));
|
||||||
|
assertEquals(_item, tuple.get(2));
|
||||||
|
assertEquals(_store, tuple.get(3));
|
||||||
|
assertEquals(_urgentOrder, tuple.get(4));
|
||||||
|
// TODO MDD more tests
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetIntNegativeValueThrowsException() {
|
||||||
|
try {
|
||||||
|
Object o = tuple.get(-1);
|
||||||
|
fail("tuple.get(-1) should throw IllegalArgumentException");
|
||||||
|
o.toString(); // clean up meaningless compiler warning
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetIntOutOfRangeThrowsException() {
|
||||||
|
try {
|
||||||
|
Object o = tuple.get(10);
|
||||||
|
fail("tuple.get(i) where i > size of TupleElements should throw IllegalArgumentException");
|
||||||
|
o.toString(); // clean up meaningless compiler warning
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Object o = tuple.get(Integer.MAX_VALUE);
|
||||||
|
fail("tuple.get(i) where i > size of TupleElements should throw IllegalArgumentException");
|
||||||
|
o.toString(); // clean up meaningless compiler warning
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetIntClass() {
|
||||||
|
assertEquals(_order, tuple.get(0, Order.class));
|
||||||
|
assertEquals(_product, tuple.get(1, Product.class));
|
||||||
|
assertEquals(_item, tuple.get(2, Item.class));
|
||||||
|
assertEquals(_store, tuple.get(3, Store.class));
|
||||||
|
assertEquals(_urgentOrder, tuple.get(4, UrgentOrder.class));
|
||||||
|
|
||||||
|
assertEquals(_urgentOrder, tuple.get(4, Order.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetIntClassExceptions() {
|
||||||
|
// duplicate code, but could be useful later if impl changes.
|
||||||
|
try {
|
||||||
|
Object o = tuple.get(-1, Order.class);
|
||||||
|
fail("tuple.get(-1) should throw IllegalArgumentException");
|
||||||
|
o.toString(); // clean up meaningless compiler warning
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Object o = tuple.get(200, Product.class);
|
||||||
|
fail("tuple.get(i) where i > size of TupleElements should throw IllegalArgumentException");
|
||||||
|
o.toString(); // clean up meaningless compiler warning
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Product product = (Product) tuple.get(0, Product.class);
|
||||||
|
fail("Expecting IllegalArgumentException when the wrong type is specified on Tuple.get(int, Class)");
|
||||||
|
product.toString(); // remove compiler warning for unused variable <sigh>
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
tuple.get(0, UrgentOrder.class);
|
||||||
|
fail("Should not be able to upcast Order to UrgentOrder");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetString() {
|
||||||
|
assertEquals(_order, tuple.get("alias1"));
|
||||||
|
assertEquals(_product, tuple.get("alias2"));
|
||||||
|
assertEquals(_item, tuple.get("alias3"));
|
||||||
|
assertEquals(_store, tuple.get("alias4"));
|
||||||
|
assertEquals(_urgentOrder, tuple.get("alias5"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
tuple.get("NotAnAlias");
|
||||||
|
fail("Expected an IllegalArgumentException for an alias that wasn't found");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
tuple.get((String) null);
|
||||||
|
fail("Expected an IllegalArgumentException for null alias");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
tuple.get("");
|
||||||
|
fail("Expected an IllegalArgumentException for null alias");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetStringClass() {
|
||||||
|
// TODO MDD convert to equals tests
|
||||||
|
assertTrue(tuple.get("alias1", Order.class) instanceof Order);
|
||||||
|
assertTrue(tuple.get("alias2", Product.class) instanceof Product);
|
||||||
|
assertTrue(tuple.get("alias3", Item.class) instanceof Item);
|
||||||
|
assertTrue(tuple.get("alias4", Store.class) instanceof Store);
|
||||||
|
|
||||||
|
try {
|
||||||
|
tuple.get("NotAnAlias", Product.class);
|
||||||
|
fail("Expected an IllegalArgumentException for an alias that wasn't found");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
tuple.get((String) null, Item.class);
|
||||||
|
fail("Expected an IllegalArgumentException for null alias");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
tuple.get("", Store.class);
|
||||||
|
fail("Expected an IllegalArgumentException for null alias");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetTupleElement() {
|
||||||
|
for (TupleElement<?> element : tuple.getElements()) {
|
||||||
|
assertEquals(((TupleElementImpl) element).getValue(), tuple.get(element));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testToArray() {
|
||||||
|
Object[] objects = tuple.toArray();
|
||||||
|
assertEquals(5, objects.length);
|
||||||
|
assertEquals(_order, objects[0]);
|
||||||
|
assertEquals(_product, objects[1]);
|
||||||
|
assertEquals(_item, objects[2]);
|
||||||
|
assertEquals(_store, objects[3]);
|
||||||
|
assertEquals(_urgentOrder, objects[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testGetElements() {
|
||||||
|
List<TupleElement<?>> elements = tuple.getElements();
|
||||||
|
assertEquals(5, elements.size());
|
||||||
|
|
||||||
|
TupleElement<Order> orderElement = (TupleElement<Order>) elements.get(0);
|
||||||
|
TupleElement<Product> productElement = (TupleElement<Product>) elements.get(1);
|
||||||
|
TupleElement<Item> itemElement = (TupleElement<Item>) elements.get(2);
|
||||||
|
TupleElement<Store> storeElement = (TupleElement<Store>) elements.get(3);
|
||||||
|
TupleElement<UrgentOrder> urgentOrderElement = (TupleElement<UrgentOrder>) elements.get(4);
|
||||||
|
|
||||||
|
assertEquals("alias1", orderElement.getAlias());
|
||||||
|
assertEquals(Order.class, orderElement.getJavaType());
|
||||||
|
assertEquals("alias2", productElement.getAlias());
|
||||||
|
assertEquals(Product.class, productElement.getJavaType());
|
||||||
|
assertEquals("alias3", itemElement.getAlias());
|
||||||
|
assertEquals(Item.class, itemElement.getJavaType());
|
||||||
|
assertEquals("alias4", storeElement.getAlias());
|
||||||
|
assertEquals(Store.class, storeElement.getJavaType());
|
||||||
|
assertEquals("alias5", urgentOrderElement.getAlias());
|
||||||
|
assertEquals(UrgentOrder.class, urgentOrderElement.getJavaType());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Begin fake entities.
|
||||||
|
class Order {
|
||||||
|
// public Order() {
|
||||||
|
// new Exception().printStackTrace();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
class UrgentOrder extends Order {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Item {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Product {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Store {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue