You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2009/07/29 21:07:57 UTC
svn commit: r799018 - in /openjpa/trunk:
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/...
Author: ppoddar
Date: Wed Jul 29 19:07:56 2009
New Revision: 799018
URL: http://svn.apache.org/viewvc?rev=799018&view=rev
Log:
OPENJPA-1198: Query by example.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java (with props)
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompareByExample.java (with props)
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ComparisonStyle.java (with props)
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManagerFactory.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java?rev=799018&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java Wed Jul 29 19:07:56 2009
@@ -0,0 +1,174 @@
+/*
+ * 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;
+
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.metamodel.Attribute;
+
+/**
+ * Tests different styles for query by example.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class TestQueryByExample extends CriteriaTest {
+
+ public void testBasicFieldsWithNonDefaultValue() {
+ String jpql = "SELECT e FROM Employee e WHERE e.rating=1 AND e.salary=1100";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setSalary(1000+100);
+ example.setRating(1);
+
+ ComparisonStyle style = null;
+ Attribute<?,?>[] excludes = null;
+ q.where(cb.example(q.from(Employee.class), example, style, excludes));
+
+ assertEquivalence(q, jpql);
+ }
+
+ public void testExcludeBasicFieldWithNonDefaultValue() {
+ String jpql = "SELECT e FROM Employee e WHERE e.salary=1100";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setSalary(1000+100);
+ example.setRating(1);
+
+ ComparisonStyle style = null;
+ Attribute<?,?>[] excludes = {Employee_.rating};
+ q.where(cb.example(q.from(Employee.class), example, style, excludes));
+
+ assertEquivalence(q, jpql);
+ }
+
+ public void testBasicFieldWithDefaultValueExcludedByDefaultStyle() {
+ String jpql = "SELECT e FROM Employee e WHERE e.rating=1";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setRating(1);
+
+ ComparisonStyle style = null;
+ Attribute<?,?>[] excludes = null;
+ q.where(cb.example(q.from(Employee.class), example, style, excludes));
+
+ executeAndCompareSQL(q, "WHERE (t0.rating = ?)");
+ assertEquivalence(q, jpql);
+ }
+
+ public void testBasicFieldWithDefaultValueCanBeIncludedByStyle() {
+ String jpql = "SELECT e FROM Employee e WHERE e.rating=1 AND e.salary=1100";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setRating(1);
+
+ ComparisonStyle style = cb.comparisonStyle();
+ Attribute<?,?>[] excludes = null;
+ q.where(cb.example(q.from(Employee.class), example, style.setExcludeDefault(false), excludes));
+
+ executeAndCompareSQL(q, "WHERE (t0.rating = ? AND t0.salary = ?)");
+ assertEquivalence(q, jpql);
+ }
+
+ public void testRelationFieldWithNonDefaultValue() {
+ String jpql = "SELECT e FROM Employee e WHERE e.rating=1 AND e.salary=1100 AND e.department.name='ExampleDept'";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setSalary(1100);
+ example.setRating(1);
+ Department dept = new Department();
+ dept.setName("ExampleDept");
+ example.setDepartment(dept);
+
+
+ ComparisonStyle style = cb.comparisonStyle();
+ Attribute<?,?>[] excludes = null;
+ q.where(cb.example(q.from(Employee.class), example, style, excludes));
+
+ executeAndCompareSQL(q, "WHERE (t1.name = ? AND t0.rating = ? AND t0.salary = ?)");
+ }
+
+ public void testRelationFieldWithNullValueIncluded() {
+ String jpql = "SELECT e FROM Employee e WHERE e.rating=1 AND e.salary=1100 AND e.department IS NULL";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setName("ExampleEmployee");
+ example.setSalary(1100);
+ example.setRating(1);
+ example.setDepartment(null);
+
+ ComparisonStyle style = cb.comparisonStyle();
+ Attribute<?,?>[] excludes = {Employee_.frequentFlierPlan, Employee_.manager, Employee_.spouse};
+ q.where(cb.example(q.from(Employee.class), example, style.setExcludeNull(false).setExcludeDefault(false),
+ excludes));
+
+ executeAndCompareSQL(q, "WHERE (1 <> 1 AND t0.DEPARTMENT_DEPTNO IS NULL "
+ + "AND t0.name = ? AND t0.rating = ? AND t0.salary = ?)");
+ }
+
+ public void testEmbeddedField() {
+ String jpql = "SELECT e FROM Employee e WHERE e.rating=1 AND e.salary=1100 AND e.department IS NULL";
+
+ CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
+
+ Employee example = new Employee();
+ example.setName("ExampleEmployee");
+ example.setSalary(1100);
+ example.setRating(1);
+ Contact contact = new Contact();
+ Address address = new Address();
+ address.setCity("Plano");
+ address.setState("TX");
+ address.setCountry("USA");
+ contact.setAddress(address);
+ example.setContactInfo(contact);
+
+ ComparisonStyle style = cb.comparisonStyle();
+ Attribute<?,?>[] excludes = {Employee_.department, Employee_.frequentFlierPlan,
+ Employee_.manager, Employee_.spouse};
+ q.where(cb.example(q.from(Employee.class), example, style, excludes));
+
+ executeAndCompareSQL(q, "WHERE (t1.city = ? AND t1.country = ? AND t1.state = ? "
+ + "AND t0.name = ? AND t0.rating = ? AND t0.salary = ?)");
+ }
+
+ void executeAndCompareSQL(CriteriaQuery<?> q, String expected) {
+ auditor.clear();
+ em.createQuery(q).getResultList();
+ assertEquals(1,auditor.getSQLs().size());
+ String actual = extract("WHERE", auditor.getSQLs().get(0));
+ assertEquals(expected, actual);
+ }
+
+ String extract(String key, String s) {
+ int index = s.indexOf(key);
+ return index == -1 ? "" : s.substring(index);
+ }
+}
Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Wed Jul 29 19:07:56 2009
@@ -364,7 +364,7 @@
return getStoreCache();
}
- public QueryBuilder getQueryBuilder() {
+ public CriteriaBuilder getQueryBuilder() {
return new CriteriaBuilder().setMetaModel(getMetamodel());
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Wed Jul 29 19:07:56 2009
@@ -1566,7 +1566,7 @@
return finalMap;
}
- public QueryBuilder getQueryBuilder() {
+ public CriteriaBuilder getQueryBuilder() {
return _emf.getQueryBuilder();
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java Wed Jul 29 19:07:56 2009
@@ -31,6 +31,7 @@
import org.apache.openjpa.kernel.ConnectionRetainModes;
import org.apache.openjpa.kernel.DetachState;
import org.apache.openjpa.kernel.RestoreState;
+import org.apache.openjpa.persistence.criteria.CriteriaBuilder;
import org.apache.openjpa.persistence.query.QueryDefinition;
/**
@@ -1141,4 +1142,12 @@
* instead: <code>em.getTransaction().getRollbackOnly()</code>
*/
public boolean getRollbackOnly();
+
+ /**
+ * Gets the QueryBuilder with OpenJPA-extended capabilities.
+ *
+ * @since 2.0.0
+ */
+ public CriteriaBuilder getQueryBuilder();
+
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManagerFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManagerFactory.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManagerFactory.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManagerFactory.java Wed Jul 29 19:07:56 2009
@@ -23,6 +23,7 @@
import javax.persistence.EntityManagerFactory;
+import org.apache.openjpa.persistence.criteria.CriteriaBuilder;
import org.apache.openjpa.persistence.query.QueryBuilder;
/**
@@ -130,4 +131,11 @@
* Gets a builder for dynamic queries.
*/
public QueryBuilder getDynamicQueryBuilder();
+
+ /**
+ * Gets the QueryBuilder with OpenJPA-extended capabilities.
+ *
+ * @since 2.0.0
+ */
+ public CriteriaBuilder getQueryBuilder();
}
Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompareByExample.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompareByExample.java?rev=799018&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompareByExample.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompareByExample.java Wed Jul 29 19:07:56 2009
@@ -0,0 +1,127 @@
+/*
+ * 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;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.openjpa.enhance.Reflection;
+
+/**
+ * An expression for query-by-example.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+class CompareByExample<T> extends PredicateImpl {
+
+ CompareByExample(CriteriaBuilder builder, ManagedType<T> type,
+ Path<T> from, T instance, ComparisonStyle style,
+ Attribute<?, ?>... excludes) {
+ super(extractOperator(style));
+ List<Attribute<?, ?>> excludeAttr = excludes == null
+ ? new ArrayList<Attribute<?,?>>() : Arrays.asList(excludes);
+
+ Set<SingularAttribute<? super T, ?>> attrs = type.getSingularAttributes();
+ for (SingularAttribute<? super T, ?> attr : attrs) {
+ if (excludeAttr.contains(attr)
+ || (style.excludeIdentity() && attr.isId())
+ || (style.excludeVersion() && attr.isVersion())) {
+ continue;
+ }
+
+ Object value = extractValue(instance, attr);
+ if ((style.excludeNull() && value == null)
+ || (style.excludeDefault() && isDefaultValue(attr.getJavaType(), value)))
+ continue;
+
+ Predicate p = null;
+ if (value == null) {
+ p = from.get(attr).isNull();
+ this.add(p);
+ continue;
+ }
+ if (attr.isAssociation()) {
+ p = new CompareByExample(builder, (ManagedType<?>)attr.getType(),
+ from.get(attr), value, style, excludes);
+ } else if (attr.getJavaType() == String.class) {
+ Expression<String> s = from.get(attr).as(String.class);
+ switch (style.getStringComparsionMode()) {
+ case EXACT : p = builder.equal(s, value);
+ break;
+ case CASE_INSENSITIVE : p = builder.equal(builder.upper(s), value.toString());
+ break;
+ case LIKE: p = builder.like(s, value.toString());
+ break;
+ }
+ } else {
+ p = builder.equal(from.get(attr), value);
+ }
+ this.add(p);
+ }
+ }
+
+ Object extractValue(T instance, SingularAttribute<? super T, ?> attr) {
+ Class<?> cls = instance.getClass();
+ Method getter = Reflection.findGetter(cls, attr.getName(), false);
+ if (getter != null)
+ return Reflection.get(instance, getter);
+ Field field = Reflection.findField(cls, attr.getName(), false);
+ if (field != null)
+ return Reflection.get(instance, field);
+ return null;
+ }
+
+ boolean isDefaultValue(Class<?> cls, Object val) {
+ if (val == null) {
+ return true;
+ }
+ if (cls == Boolean.class || cls == boolean.class) {
+ return Boolean.FALSE.equals(val);
+ } else if (cls == Character.class || cls == char.class) {
+ return ((Character) val).charValue() == 0;
+ } else if (cls == Byte.class || cls == byte.class
+ || cls == Double.class || cls == double.class
+ || cls == Float.class || cls == float.class
+ || cls == Long.class || cls == long.class
+ || cls == Integer.class || cls == int.class
+ || cls == Short.class || cls == short.class) {
+ return ((Number) val).intValue() == 0;
+ } else if (cls == String.class) {
+ return "".equals(val);
+ } else {
+ return false;
+ }
+ }
+
+ static <T> BooleanOperator extractOperator(ComparisonStyle style) {
+ return style == null ? BooleanOperator.AND : style.isDisjunction() ? BooleanOperator.OR : BooleanOperator.AND;
+ }
+}
Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompareByExample.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ComparisonStyle.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ComparisonStyle.java?rev=799018&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ComparisonStyle.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ComparisonStyle.java Wed Jul 29 19:07:56 2009
@@ -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.criteria;
+
+
+/**
+ * Defines a comparison style to be applied for query-by-example attribute comparison.
+ *
+ * @author Pinaki Poddar
+ *
+ * @since 2.0.0
+ *
+ */
+public interface ComparisonStyle {
+ public static enum StringComparisonMode {
+ EXACT, // compares exactly preserving case
+ CASE_INSENSITIVE, // compares ignoring case
+ LIKE // compares with LIKE() operator
+ }
+
+ /**
+ * Affirms if the attribute comparisons are OR'ed.
+ * Defaults to false.
+ */
+ boolean isDisjunction();
+
+ /**
+ * Sets whether the comparison to OR the attribute comparisons.
+ */
+ ComparisonStyle setDisjunction(boolean flag);
+
+ /**
+ * Affirms if the null-valued attribute be excluded from comparison.
+ * Defaults to true.
+ */
+ boolean excludeNull();
+
+ /**
+ * Sets whether the comparison excludes null-valued attributes.
+ */
+ ComparisonStyle setExcludeNull(boolean flag);
+
+ /**
+ * Affirms if the identity attribute be excluded from comparison.
+ * Defaults to true.
+ */
+ boolean excludeIdentity();
+
+ /**
+ * Sets whether the comparison excludes identity attribute.
+ */
+ ComparisonStyle setExcludeIdentity(boolean flag);
+
+ /**
+ * Affirms if the version attribute be excluded from comparison.
+ * Defaults to true.
+ */
+ boolean excludeVersion();
+
+ /**
+ * Sets whether the comparison excludes version attribute.
+ */
+ ComparisonStyle setExcludeVersion(boolean flag);
+
+ /**
+ * Affirms if the default-valued attribute be excluded from comparison.
+ * Defaults to true.
+ */
+
+ boolean excludeDefault();
+
+ /**
+ * Sets whether the comparison excludes default-valued attributes.
+ */
+ ComparisonStyle setExcludeDefault(boolean flag);
+
+ /**
+ * Gets how string-valued attributes be compared.
+ */
+ StringComparisonMode getStringComparsionMode();
+
+ /**
+ * Sets the comparison mode for String-valued attributes.
+ */
+ ComparisonStyle setStringComparisonMode(StringComparisonMode mode);
+
+ /**
+ * Default implementation.
+ *
+ */
+ static class Default implements ComparisonStyle {
+ private boolean excludeDefault = true;
+ private boolean excludeNull = true;
+ private boolean excludeIdentity = true;
+ private boolean excludeVersion = true;
+ private boolean disjunction = false;
+ private StringComparisonMode stringMode = StringComparisonMode.EXACT;
+
+ public boolean excludeDefault() {
+ return excludeDefault;
+ }
+
+ public boolean excludeNull() {
+ return excludeNull;
+ }
+
+ public StringComparisonMode getStringComparsionMode() {
+ return stringMode;
+ }
+
+ public boolean isDisjunction() {
+ return disjunction;
+ }
+
+ public ComparisonStyle setExcludeDefault(boolean flag) {
+ excludeDefault = flag;
+ return this;
+ }
+
+ public ComparisonStyle setExcludeNull(boolean flag) {
+ excludeNull = flag;
+ return this;
+ }
+
+ public ComparisonStyle setStringComparisonMode(StringComparisonMode mode) {
+ stringMode = mode;
+ return this;
+ }
+
+ public ComparisonStyle setDisjunction(boolean flag) {
+ disjunction = flag;
+ return this;
+ }
+
+ public boolean excludeIdentity() {
+ return excludeIdentity;
+
+ }
+
+ public ComparisonStyle setExcludeIdentity(boolean flag) {
+ excludeIdentity = flag;
+ return this;
+ }
+
+ public boolean excludeVersion() {
+ return excludeVersion;
+
+ }
+
+ public ComparisonStyle setExcludeVersion(boolean flag) {
+ excludeVersion = flag;
+ return this;
+ }
+ }
+}
+
+
Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ComparisonStyle.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java Wed Jul 29 19:07:56 2009
@@ -31,12 +31,15 @@
import javax.persistence.criteria.CompoundSelection;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.From;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.QueryBuilder;
import javax.persistence.criteria.Selection;
import javax.persistence.criteria.Subquery;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
import org.apache.openjpa.kernel.ExpressionStoreQuery;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
@@ -688,4 +691,45 @@
public CompoundSelection<Tuple> tuple(Selection<?>... selections) {
return new TupleSelection<Tuple>(Tuple.class, selections);
}
+
+ /**
+ * Create a predicate based upon the attribute values of a given
+ * "example" entity instance. The predicate is the conjunction
+ * or disjunction of predicates for subset of attribute of the entity.
+ * <br>
+ * By default, all the singular entity attributes (the basic, embedded
+ * and uni-cardinality relations) that have a non-null or non-default
+ * value for the example instance and are not an identity or version
+ * attribute are included. The comparable attributes can be further
+ * pruned by specifying variable list of attributes as the final argument.
+ *
+ * @param example an instance of an entity class
+ *
+ * @param style specifies various aspects of comparison such as whether
+ * non-null attribute values be included, how string-valued attribute be
+ * compared, whether the individual attribute based predicates are ANDed
+ * or ORed etc.
+ *
+ * @param excludes list of attributes that are excluded from comparison.
+ *
+ * @return a predicate
+ */
+ public <T> Predicate example(From<?, T> from, T example, ComparisonStyle style, Attribute<?,?>... excludes) {
+ if (from == null)
+ throw new NullPointerException();
+ if (example == null) {
+ return from.isNull();
+
+ }
+ ManagedType<T> type = (ManagedType<T>)_model.type(example.getClass());
+ return new CompareByExample<T>(this, type, from, example,
+ style == null ? comparisonStyle() : style, excludes);
+ }
+
+ /**
+ * Create a style to tune different aspects of comparison by example.
+ */
+ public ComparisonStyle comparisonStyle() {
+ return new ComparisonStyle.Default();
+ }
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java Wed Jul 29 19:07:56 2009
@@ -62,7 +62,7 @@
* @return expression
*/
public <Y> Expression<Y> as(Class<Y> type) {
- return new Expressions.CastAs<Y>(type, this);
+ return type == getJavaType() ? (Expression<Y>)this : new Expressions.CastAs<Y>(type, this);
}
/**
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java Wed Jul 29 19:07:56 2009
@@ -19,17 +19,25 @@
package org.apache.openjpa.persistence.criteria;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.From;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.QueryBuilder;
import javax.persistence.criteria.Selection;
import javax.persistence.criteria.Subquery;
import javax.persistence.criteria.QueryBuilder.Trimspec;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.SingularAttribute;
+import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.Literal;
import org.apache.openjpa.kernel.exps.Value;
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java Wed Jul 29 19:07:56 2009
@@ -27,6 +27,7 @@
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
+import java.util.TreeSet;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.CollectionAttribute;
@@ -186,7 +187,7 @@
*
*/
public java.util.Set<Attribute<X, ?>> getDeclaredAttributes() {
- return filter(attrs, new HashSet<Attribute<X, ?>>(),
+ return filter(attrs, new TreeSet<Attribute<X, ?>>(),
declaredAttributeFilter);
}
@@ -195,7 +196,7 @@
*
*/
public java.util.Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
- return filter(attrs, new HashSet<SingularAttribute<? super X, ?>>(),
+ return filter(attrs, new TreeSet<SingularAttribute<? super X, ?>>(),
singularAttributeFilter);
}
@@ -204,7 +205,7 @@
*
*/
public java.util.Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
- return filter(attrs, new HashSet<SingularAttribute<X, ?>>(),
+ return filter(attrs, new TreeSet<SingularAttribute<X, ?>>(),
declaredAttributeFilter,
singularAttributeFilter);
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java?rev=799018&r1=799017&r2=799018&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java Wed Jul 29 19:07:56 2009
@@ -52,7 +52,7 @@
* @param <X> The type that contains this attribute
* @param <Y> The type of this attribute
*/
- public static abstract class Member<X, Y> implements Attribute<X, Y> {
+ public static abstract class Member<X, Y> implements Attribute<X, Y>, Comparable<Member<X,Y>> {
public final AbstractManagedType<X> owner;
public final FieldMetaData fmd;
@@ -130,6 +130,10 @@
return PersistentAttributeType.ELEMENT_COLLECTION;
return PersistentAttributeType.BASIC;
}
+
+ public int compareTo(Member<X, Y> o) {
+ return fmd.getName().compareTo(o.fmd.getName());
+ }
}