[hibernate-commits] Hibernate SVN: r18867 - in core/trunk: entitymanager/src/main/docbook/en/modules and 1 other directory.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Wed Feb 24 02:31:59 EST 2010
Author: steve.ebersole at jboss.com
Date: 2010-02-24 02:31:58 -0500 (Wed, 24 Feb 2010)
New Revision: 18867
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent
core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml
Log:
HHH-4936 - Document JPA criteria queries
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent 2010-02-24 00:11:24 UTC (rev 18866)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent 2010-02-24 07:31:58 UTC (rev 18867)
@@ -1,5 +1,5 @@
<!ENTITY versionNumber "WORKING">
<!ENTITY today "TODAY">
<!ENTITY copyrightYear "2004">
-<!ENTITY copyrightHolder "Red Hat Middleware, LLC.">
+<!ENTITY copyrightHolder "Red Hat, Inc.">
<!ENTITY semi ";">
Modified: core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml
===================================================================
--- core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml 2010-02-24 00:11:24 UTC (rev 18866)
+++ core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml 2010-02-24 07:31:58 UTC (rev 18867)
@@ -26,218 +26,532 @@
<chapter id="querycriteria">
<title>Criteria Queries</title>
- <note>
- <para>
- This chapter elaborates on the material discussed in
- <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle>
- of<citation>JPA 2 Specification</citation>.
- </para>
- </note>
-
<para>
Criteria queries are a programmatic, type-safe way to express a query. They are type-safe
in terms of using interfaces and classes to represent various structural parts of a query
such as the query itself, or the select clause, or an order-by, etc. They can also be
type-safe in terms of referencing attributes as we will see in a bit. Users of the older
- Hibernate
- <interfacename>org.hibernate.Criteria</interfacename>
- query API will recognize
+ Hibernate <interfacename>org.hibernate.Criteria</interfacename> query API will recognize
the general approach, though we believe the JPA API to be superior as it represents a clean
- look at the lessons learned from that API. There are essentially 2 phases to performing
- a criteria query:
+ look at the lessons learned from that API.
+ </para>
- <orderedlist>
- <listitem>
- <para>
- <link linkend="querycriteria-building">Building the criteria instance</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="querycriteria-executing">Executing the criteria instance</link>
- </para>
- </listitem>
- </orderedlist>
+ <para>
+ Criteria queries are essentially an object graph, where each part of the graph represents an increasing
+ (as we navigate down this graph) more atomic part of query. The first step in performing a criteria query
+ is building this graph. The <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ interface is the first thing with which you need to become acquainted to begin using criteria queries. Its
+ role is that of a factory for all the individual pieces of the criteria. You obtain a
+ <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename> instance by calling the
+ <methodname>getCriteriaBuilder</methodname> method of the
+ <interfacename>javax.persistence.EntityManagerFactory</interfacename>
</para>
+ <programlisting>CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();</programlisting>
- <section id="querycriteria-building">
- <title>Criteria query building</title>
+ <para>
+ The next step is to obtain a <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>.
+ You do this by one of the 3 methods on <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ for this puropse.
+ </para>
+
+ <programlisting><![CDATA[CriteriaQuery<T> createQuery(Class<T>)]]></programlisting>
+ <programlisting><![CDATA[CriteriaQuery<Tuple> createTupleQuery()]]></programlisting>
+ <programlisting><![CDATA[CriteriaQuery<Object> createQuery()]]></programlisting>
+
+ <para>
+ Each serves a different purpose depending on the expected type of the query results.
+ </para>
+
+ <note>
<para>
- Criteria queries are essentially an object graph, where each part of the graph
- represents an increasing (as we navigate down this graph) more atomic part of
- query. The first step in performing a criteria query is building this graph.
+ <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle> of the
+ <citation><xref linkend="JPA2"/></citation> already contains a decent amount of reference material
+ pertaining to the various parts of a criteria query. So rather than duplicate all that content here,
+ lets instead look at some of the more widely (anticipated) usages of the API.
</para>
- <section id="querycriteria-builder">
- <title>CriteriaBuilder</title>
+ </note>
+
+ <section id="querycriteria-typedquery">
+ <title>Typed criteria queries</title>
+ <programlisting><![CDATA[CriteriaQuery<T> createQuery(Class<T>)]]></programlisting>
+ <para>
+ The type of the criteria query (aka the <T>) indicates the expected types in the
+ query result. This might be an entity, an Integer, or any other object.
+ </para>
+
+ <section id="querycriteria-typedquery-entity">
+ <title>Selecting an entity</title>
<para>
- The
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- interface is the
- first thing with which you need to become acquainted to begin using criteria queries. Its role
- is a factory for all the individual pieces of the criteria. You obtain a
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- instance by calling
- the
- <methodname>javax.persistence.EntityManagerFactory.getCriteriaBuilder</methodname>
- method:
+ This the most used form of query in Hibernate Query Language (HQL) and Hibernate Criteria Queries.
+ You have an entity and you want to select one or more of that entity based on some condition.
</para>
- <programlisting>CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();</programlisting>
+ <example id="ex-criteria-typedquery-entity">
+ <title>Selecting the root entity</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.entity.1" coords="">
+ <area id="ex.criteria.typedquery.entity.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.entity.1.c2" coords='6'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.entity.2" coords="3" />
+ <area id="ex.criteria.typedquery.entity.3" coords="4" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Person> criteria = builder.createQuery( Person.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( personRoot );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Person> people = em.createQuery( criteria ).getResultList();
+for ( Person person : people ) { ... }]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.entity.1">
+ <para>
+ We use the form <emphasis>createQuery( Person.class )</emphasis>
+ here because the expected returns are in fact Person entities as we see when we
+ begin processing the results.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.entity.2">
+ <para>
+ <emphasis>personCriteria.select( personRoot )</emphasis> here is completely
+ unneeded in this specific case because of the fact that <emphasis>personRoot</emphasis>
+ will be the implied selection since we have only a single root. It was done here only
+ for completeness of an example
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.entity.3">
+ <para>
+ <emphasis>Person_.eyeColor</emphasis> is an example of the static form of metamodel
+ reference. We will use that form exclusively in this chapter.
+ See (todo link to metamodel section once written).
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
</section>
- <section id="querycriteria-criteria">
- <title>CriteriaQuery creation</title>
+
+ <section id="querycriteria-typedquery-expression">
+ <title>Selecting a value</title>
<para>
- Once you have the
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- reference
- you can begin building the pieces of the criteria query. First, you will need a
- <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>
- instance.
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- defines 3 methods
- for obtaining a
- <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>
- instance:
+ The simplest form of selecting a value is selecting a particular attribute from an entity. But
+ this might also be an aggregation, a mathematical operation, etc.
</para>
- <itemizedlist>
- <listitem>
- <programlisting><![CDATA[CriteriaQuery<T> createQuery(Class<T>)]]></programlisting>
- </listitem>
- <listitem>
- <programlisting><![CDATA[CriteriaQuery<Tuple> createTupleQuery()]]></programlisting>
- </listitem>
- <listitem>
- <programlisting><![CDATA[CriteriaQuery<Object> createQuery()]]></programlisting>
- </listitem>
- </itemizedlist>
+ <example id="ex-criteria-typedquery-attribute">
+ <title>Selecting an attribute</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.attr.1" coords="">
+ <area id="ex.criteria.typedquery.attr.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.attr.1.c2" coords='5'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.attr.2" coords="3" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( personRoot.get( Person_.age ) );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Integer> ages = em.createQuery( criteria ).getResultList();
+for ( Integer age : ages ) { ... } ]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.attr.1">
+ <para>
+ Notice again the typing of the query based on the anticipated result type(s). Here
+ we are specifying <classname>java.lang.Integer</classname> as the type of the
+ <emphasis>Person#age</emphasis> attribute is <classname>java.lang.Integer</classname>.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.attr.2">
+ <para>
+ We need to bind the fact that we are interested in the age associated with the
+ <emphasis>personRoot</emphasis>. We might have multiple references to the Person
+ entity in the query so we need to identify (aka qualify) which
+ <emphasis>Person#age</emphasis> we mean.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ <example id="ex-criteria-typedquery-expression">
+ <title>Selecting an expression</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <area id="ex.criteria.typedquery.expr.1" coords="3" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( builder.max( personRoot.get( Person_.age ) ) );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+Integer maxAge = em.createQuery( criteria ).getSingleResult();]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.expr.1">
+ <para>
+ Here we see <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ used to obtain a <emphasis>MAX</emphasis> expression. These expression building
+ methods return <interfacename>javax.persistence.criteria.Expression</interfacename>
+ instances typed according to various rules. The rule for a <emphasis>MAX</emphasis>
+ expression is that the expression type is the same as that of the underlying attribute.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ </section>
+
+ <section id="querycriteria-typedquery-multiselect">
+ <title>Selecting multiple values</title>
<para>
- Each serves a different purpose depending on the expected type of the query results. The type
- is "carried forward" to the
- <interfacename>javax.persistence.TypedQuery</interfacename>
- we
- create from this
- <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>
- as
- we will see later in<xref linkend="querycriteria-executing"/>later.
+ There are actually a few different ways to select multiple values using criteria queries. We will
+ explore 2 options here, but an alternative recommended approach is to use tuples as
+ described in <xref linkend="querycriteria-tuple"/>
</para>
- <section id="querycriteria-criteria-typed">
- <title>Typed CriteriaQuery</title>
- <programlisting>
- <![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery(Person.class);]]></programlisting>
- <para>
- Basically this is saying to create a criteria where the results of this query will be of type
- Person. Person might be an entity or it might not. The type could even be simple types like
- <classname>java.lang.Integer</classname>,<classname>java.lang.String</classname>, etc. We
- will discuss this topic in more detail in
- <xref linkend="querycriteria-selection"/>
- </para>
- </section>
- <section id="querycriteria-criteria-tuple">
- <title>Tuple CriteriaQuery</title>
- <programlisting>
- <![CDATA[CriteriaQuery<Tuple> personCriteria = builder.createTupleQuery();]]></programlisting>
- <programlisting>
- <![CDATA[CriteriaQuery<Tuple> personCriteria = builder.createQuery(Tuple.class);]]></programlisting>
- <para>
- These two forms are exactly the same. Both say to create a criteria where the results of this
- query will be of type<interfacename>javax.persistence.Tuple</interfacename>. The term tuple is
- taken from mathematics, but its intent here is simply to mean a plurality; namely we are saying
- that each query result will actually be multiple values, a projection. The
- <interfacename>javax.persistence.Tuple</interfacename>
- instance gives us typed access to these
- multiple result values after the query has been executed. We will discuss accessing the query
- results via a
- <interfacename>javax.persistence.Tuple</interfacename>
- in
- <xref linkend="querycriteria-executing"/>.
- </para>
- </section>
- <section id="querycriteria-criteria-untyped">
- <title>Untyped CriteriaQuery</title>
- <programlisting>
- <![CDATA[CriteriaQuery<Object> personCriteria = builder.createQuery();]]></programlisting>
- <programlisting>
- <![CDATA[CriteriaQuery<Object> personCriteria = builder.createQuery(Object.class);]]></programlisting>
- <para>
- These two forms are exactly the same. Both say to create a criteria where the results of this
- query could be anything. Not generally recommended as you obviously lose the type safety.
- </para>
- </section>
+ <example id="ex-criteria-typedquery-array">
+ <title>Selecting an array</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.array.1" coords="">
+ <area id="ex.criteria.typedquery.array.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.array.1.c2" coords='7'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.array.2" coords="5" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
+Root<Person> personRoot = criteria.from( Person.class );
+Path<Long> idPath = personRoot.get( Person_.id );
+Path<Integer> agePath = personRoot.get( Person_.age );
+criteria.select( builder.array( idPath, agePath ) );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Object[]> valueArray = em.createQuery( criteria ).getResultList();
+for ( Object[] values : valueArray ) {
+ final Long id = (Long) values[0];
+ final Integer age = (Integer) values[1];
+ ...
+}]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.array.1">
+ <para>
+ Technically this is classified as a typed query, but as you can see in handling the
+ results that is sort of misleading. Anyway, the expected result type here is an
+ array.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.array.2">
+ <para>
+ Here we see the use of the <methodname>array</methodname> method of the
+ <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename> which
+ explicitly combines individual selections into a
+ <interfacename>javax.persistence.criteria.CompoundSelection</interfacename>.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ <example id="ex-criteria-typedquery-array2">
+ <title>Selecting an array (2)</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.array2.1" coords="">
+ <area id="ex.criteria.typedquery.array2.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.array2.1.c2" coords='7'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.array2.2" coords="5" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
+Root<Person> personRoot = criteria.from( Person.class );
+Path<Long> idPath = personRoot.get( Person_.id );
+Path<Integer> agePath = personRoot.get( Person_.age );
+criteria.multiselect( idPath, agePath );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Object[]> valueArray = em.createQuery( criteria ).getResultList();
+for ( Object[] values : valueArray ) {
+ final Long id = (Long) values[0];
+ final Integer age = (Integer) values[1];
+ ...
+} ]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.array2.1">
+ <para>
+ Just as we saw in <xref linkend="ex-criteria-typedquery-array"/> we have
+ a "typed" criteria query returning an Object array.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.array2.2">
+ <para>
+ This actually functions exactly the same as what we saw in
+ <xref linkend="ex-criteria-typedquery-array"/>. The <methodname>multiselect</methodname>
+ method behaves slightly differently based on the type given when the criteria query
+ was first built, but in this case it says to select and return an
+ <emphasis>Object[]</emphasis>.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
</section>
- <section id="querycriteria-from">
- <title>FROM clause</title>
- <blockquote>
- <attribution>
- <citation>
- <citation>JPA 2 Specification</citation>
- </citation>
- </attribution>
- <para>
- A CriteriaQuery object defines a query over one or more entity, embeddable, or basic abstract
- schema types. The root objects of the query are entities, from which the other types are reached
- by navigation.
- </para>
- </blockquote>
- <para>All the individual parts of the FROM clause (roots, joins, paths) implement the
- <interfacename>javax.persistence.criteria.From</interfacename>
- interface.
+
+ <section id="querycriteria-typedquery-construct">
+ <title>Selecting a wrapper</title>
+ <para>
+ Another alternative to <xref linkend="querycriteria-typedquery-multiselect"/> is to instead select
+ an object that will "wrap" the multiple values. Going back to the example query there, rather than
+ returning an array of <emphasis>[Person#id, Person#age]</emphasis> instead declare a class
+ that holds these values and instead return that.
</para>
- <section id="querycriteria-from-root">
- <title>Roots</title>
- <para>Roots define the basis from which all joins, paths and attributes are available in the query. It
- is
- the root of the portion of your domain model you wish to query against. In a criteria query, a root
- is always an entity. Roots are defined and added to the criteria by the overloaded
- <methodname>from</methodname>
- methods on<interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>:
- </para>
- <programlisting><![CDATA[<X> Root<X> from(Class<X>)]]></programlisting>
- <programlisting><![CDATA[<X> Root<X> from(EntityType<X>)]]></programlisting>
+ <example id="ex-criteria-typedquery-construct">
+ <title>Selecting an wrapper</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.construct.1" coords="" >
+ <area id="ex.criteria.typedquery.construct.1.c1" coords="1" />
+ <area id="ex.criteria.typedquery.construct.1.c2" coords="4" />
+ </areaset>
+ <areaset id="ex.criteria.typedquery.construct.2" coords="">
+ <area id="ex.criteria.typedquery.construct.2.c1" coords='11'/>
+ <area id="ex.criteria.typedquery.construct.2.c2" coords='21'/>
+ </areaset>
+ <areaset id="ex.criteria.typedquery.construct.3" coords="" >
+ <area id="ex.criteria.typedquery.construct.3.c1" coords="13" />
+ <area id="ex.criteria.typedquery.construct.3.c2" coords="14" />
+ </areaset>
+ </areaspec>
+ <programlisting><![CDATA[public class PersonWrapper {
+ private final Long id;
+ private final Integer age;
+ public PersonWrapper(Long id, Integer age) {
+ this.id = id;
+ this.age = age;
+ }
+ ...
+}
+...
+CriteriaQuery<PersonWrapper> criteria = builder.createQuery( PersonWrapper.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select(
+ builder.construct(
+ PersonWrapper.class,
+ personRoot.get( Person_.id ),
+ personRoot.get( Person_.age )
+ )
+);
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<PersonWrapper> people = em.createQuery( criteria ).getResultList();
+for ( PersonWrapper person : people ) { ... }]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.construct.1">
+ <para>
+ First we see the simple definition of the wrapper object we will be using to
+ wrap our result values. Specifically notice the constructor and its argument types.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.construct.2">
+ <para>
+ Since we will be returning <emphasis>PersonWrapper</emphasis> objects, we
+ use <emphasis>PersonWrapper</emphasis> as the type of our criteria query.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.construct.3">
+ <para>
+ Here we see another new <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ method, <methodname>construct</methodname>, which is used to builder a wrapper
+ expression. Basically for every row in the result we are saying we would like
+ a <emphasis>PersonWrapper</emphasis> instantiated by the matching constructor. This
+ wrapper expression is then passed as the select.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ </section>
+
+ </section>
+
+ <section id="querycriteria-tuple">
+ <title>Tuple criteria queries</title>
+ <para>
+ A better approach to <xref linkend="querycriteria-typedquery-multiselect"/> is to either use
+ a wrapper (which we just saw in <xref linkend="querycriteria-typedquery-construct"/>) or using
+ the <interfacename>javax.persistence.Tuple</interfacename> contract.
+ </para>
+
+ <example id="ex-criteria-typedquery-tuple">
+ <title>Selecting a tuple</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.tuple.1" coords="">
+ <area id="ex.criteria.typedquery.tuple.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.tuple.1.c2" coords='7'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.tuple.2" coords="5" />
+ <areaset id="ex.criteria.typedquery.tuple.3" coords="">
+ <area id="ex.criteria.typedquery.tuple.3.c1" coords='9'/>
+ <area id="ex.criteria.typedquery.tuple.3.c2" coords='10'/>
+ </areaset>
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
+Root<Person> personRoot = criteria.from( Person.class );
+Path<Long> idPath = personRoot.get( Person_.id );
+Path<Integer> agePath = personRoot.get( Person_.age );
+criteria.multiselect( idPath, agePath );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Tuple> tuples = em.createQuery( criteria ).getResultList();
+for ( Tuple tuple : valueArray ) {
+ assert tuple.get( 0 ) == tuple.get( idPath );
+ assert tuple.get( 1 ) == tuple.get( agePath );
+ ...
+} ]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.tuple.1">
+ <para>
+ Here we see the use of a new <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename> building method,
+ <methodname>createTupleQuery</methodname>. This is exactly equivalent to calling
+ <emphasis>builder.createQuery( Tuple.class )</emphasis>. It signifies that we want
+ to access the results through the <interfacename>javax.persistence.Tuple</interfacename> contract.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.tuple.2">
+ <para>
+ Again we see the use of the <methodname>multiselect</methodname> method, just like
+ in <xref linkend="ex-criteria-typedquery-array2"/>. The difference here is that the
+ type of the <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename> was defined
+ as <interfacename>javax.persistence.Tuple</interfacename> so the compound selections in
+ this case are interpreted to be the tuple elements.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.tuple.3">
+ <para>
+ Here we see <interfacename>javax.persistence.Tuple</interfacename> allowing different types of
+ access to the results, which we will expand on next.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+
+ <section id="querycriteria-tuple-access">
+ <title>Accessing tuple elements</title>
+ <para>
+ The <interfacename>javax.persistence.Tuple</interfacename> contract provides 3 basic forms of
+ access to the underlying elements:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>typed</term>
+ <listitem>
+ <programlisting><![CDATA[<X> X get(TupleElement<X> tupleElement)]]></programlisting>
+ <para>
+ This allows typed access to the underlying tuple elements. We see this in
+ <xref linkend="ex-criteria-typedquery-tuple"/> in the <emphasis>tuple.get( idPath )</emphasis>
+ and <emphasis>tuple.get( agePath )</emphasis> calls. Just about everything is a
+ <interfacename>javax.persistence.TupleElement</interfacename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>positional</term>
+ <listitem>
+ <programlisting><![CDATA[Object get(int i)]]></programlisting>
+ <programlisting><![CDATA[<X> X get(int i, Class<X> type)]]></programlisting>
+ <para>
+ Very similar to what we saw in <xref linkend="ex-criteria-typedquery-array"/> and
+ <xref linkend="ex-criteria-typedquery-array2"/> in terms of positional access. Only the
+ second form here provides typing, because the user explicitly provides the typing
+ on access. We see this in <xref linkend="ex-criteria-typedquery-tuple"/> in
+ the <emphasis>tuple.get( 0 )</emphasis> and <emphasis>tuple.get( 1 )</emphasis> calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>aliased</term>
+ <listitem>
+ <programlisting><![CDATA[Object get(String alias)]]></programlisting>
+ <programlisting><![CDATA[<X> X get(String alias, Class<X> type)]]></programlisting>
+ <para>
+ Again, only the second form here provides typing, because the user explicitly provides
+ the typing on access. We have not seen an example of using this, but its trivial. We
+ would simply, for example, have applies an alias to either of the paths like
+ <emphasis>idPath.alias( "id" )</emphasis> and/or <emphasis>agePath.alias( "age" )</emphasis>
+ and we could have accessed the individual tuple elements by those specified aliases.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ </section>
+
+
+
+ <section id="querycriteria-from">
+ <title>FROM clause</title>
+ <blockquote>
+ <attribution>
+ <citation><xref linkend="JPA2"/></citation>
+ </attribution>
+ <para>
+ A CriteriaQuery object defines a query over one or more entity, embeddable, or basic abstract
+ schema types. The root objects of the query are entities, from which the other types are reached
+ by navigation.
+ </para>
+ </blockquote>
+
+ <note>
+ <para>
+ All the individual parts of the FROM clause (roots, joins, paths) implement the
+ <interfacename>javax.persistence.criteria.From</interfacename> interface.
+ </para>
+ </note>
+
+ <section id="querycriteria-from-root">
+ <title>Roots</title>
+ <para>
+ Roots define the basis from which all joins, paths and attributes are available in the query. In
+ a criteria query, a root is always an entity. Roots are defined and added to the criteria by
+ the overloaded <methodname>from</methodname> methods on
+ <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>:
+ </para>
+ <programlisting><![CDATA[<X> Root<X> from(Class<X>)]]></programlisting>
+ <programlisting><![CDATA[<X> Root<X> from(EntityType<X>)]]></programlisting>
+ <example>
+ <title>Adding a root</title>
<programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
// create and add the root
person.from( Person.class );
...]]></programlisting>
- <para>Criteria queries may define multiple roots, the effect of which is to create a cartesean product
- between the newly added root and the others. Here is an example matching all single men and all
- single women:
- </para>
- <programlisting><![CDATA[CriteriaQuery query = builder.createQuery();
+ </example>
+
+ <para>
+ Criteria queries may define multiple roots, the effect of which is to create a
+ <ulink url="http://en.wikipedia.org/wiki/Cartesian_product">cartesian product</ulink>
+ between the newly added root and the others. Here is an example matching all single men and all
+ single women:
+ </para>
+ <programlisting><![CDATA[CriteriaQuery query = builder.createQuery();
Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
- builder.equal(
- men.get( Person_.gender ),
- Gender.MALE
- ),
- builder.equal(
- men.get( Person_.relationshipStatus ),
- RelationshipStatus.SINGLE
- )
+ builder.equal( men.get( Person_.gender ), Gender.MALE ),
+ builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
Predicate womenRestriction = builder.and(
- builder.equal(
- women.get( Person_.gender ),
- Gender.FEMALE
- ),
- builder.equal(
- women.get( Person_.relationshipStatus ),
- RelationshipStatus.SINGLE
- )
+ builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
+ builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
-query.where(
- builder.and( menRestriction, womenRestriction )
-);]]></programlisting>
- </section>
- <section id="querycriteria-from-join">
- <title>Joins</title>
- <para>Joins allow navigation from other
- <interfacename>javax.persistence.criteria.From</interfacename>
- to either association or embedded attributes. Joins are created by the numerous overloaded
- <methodname>join</methodname>
- methods of the
- <interfacename>javax.persistence.criteria.From</interfacename>
- interface:
- </para>
+query.where( builder.and( menRestriction, womenRestriction ) );]]></programlisting>
+ </section>
+
+ <section id="querycriteria-from-join">
+ <title>Joins</title>
+ <para>Joins allow navigation from other
+ <interfacename>javax.persistence.criteria.From</interfacename>
+ to either association or embedded attributes. Joins are created by the numerous overloaded
+ <methodname>join</methodname>
+ methods of the
+ <interfacename>javax.persistence.criteria.From</interfacename>
+ interface:
+ </para>
+ <example id="criteria-join-singular">
+ <title>Example with Embedded and ManyToOne</title>
<programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
Root<Person> personRoot = person.from( Person.class );
// Person.address is an embedded attribute
@@ -245,128 +559,105 @@
// Address.country is a ManyToOne
Join<Address,Country> addressCountry = personAddress.join( Address_.country );
...]]></programlisting>
- <para>An example with collection attributes:</para>
+ </example>
+ <example id="criteria-join-plural">
+ <title>Example with Collections</title>
<programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
Root<Person> personRoot = person.from( Person.class );
Join<Person,Order> orders = personRoot.join( Person_.orders );
Join<Order,LineItem> orderLines = orders.join( Order_.lineItems );
...]]></programlisting>
- </section>
- <section id="querycriteria-from-fetch">
- <title>Fetches</title>
- <para>todo</para>
- </section>
+ </example>
</section>
+
+ <section id="querycriteria-from-fetch">
+ <title>Fetches</title>
+ <para>
+ Just like in HQL and EJB-QL, we can specify that associated data be fetched along with the owner.
+ Fetches are created by the numerous overloaded <methodname>fetch</methodname>
+ methods of the <interfacename>javax.persistence.criteria.From</interfacename>
+ interface:
+ </para>
+ <example id="criteria-fetch-singular">
+ <title>Example with Embedded and ManyToOne</title>
+ <programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+Root<Person> personRoot = person.from( Person.class );
+// Person.address is an embedded attribute
+Join<Person,Address> personAddress = personRoot.fetch( Person_.address );
+// Address.country is a ManyToOne
+Join<Address,Country> addressCountry = personAddress.fetch( Address_.country );
+...]]></programlisting>
+ </example>
+ <note>
+ <para>
+ Technically speaking, embedded attributes are always fetched with their owner. However
+ in order to define the fetching of <emphasis>Address#country</emphasis> we needed
+ a <interfacename>javax.persistence.criteria.Fetch</interfacename> for its parent path.
+ </para>
+ </note>
+ <example id="criteria-fetch-plural">
+ <title>Example with Collections</title>
+ <programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+Root<Person> personRoot = person.from( Person.class );
+Join<Person,Order> orders = personRoot.fetch( Person_.orders );
+Join<Order,LineItem> orderLines = orders.fetch( Order_.lineItems );
+...]]></programlisting>
+ </example>
+ </section>
+
+ </section>
+
<section id="querycriteria-path">
<title>Path expressions</title>
<note>
<para>
- Roots, joins and fetches are themselves paths as well
+ Roots, joins and fetches are themselves paths as well.
</para>
</note>
- <para>todo</para>
</section>
- <section id="querycriteria-selection">
- <title>Selections</title>
- <para>todo</para>
- </section>
- </section>
- <section id="querycriteria-executing">
- <title>Criteria query execution</title>
- <para>todo</para>
- </section>
- <section id="querycriteria-common">
- <title>Common use cases</title>
- <section id="querycriteria-common-selectroot">
- <title>Selecting the root entity</title>
- <programlisting><![CDATA[// get all people with brown eyes
-CriteriaQuery<Person> personCriteria = build.createQuery( Person.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-// specifying select here is not strictly needed because 'personRoot'
-// will be the implied selection since we have only a single root;
-// but done here for explicitness
-personCriteria.select( personRoot );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Person> people = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-selectassociation">
- <title>Selecting an association</title>
- <programlisting><![CDATA[// get the gender of all people with brown eyes
-CriteriaQuery<Gender> personCriteria = build.createQuery( Gender.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-// specifying select here is not strictly needed because 'personRoot'
-// will be the implied selection since we have only a single root;
-// but done here for explicitness
-personCriteria.select( personRoot );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Person> people = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-selectvalue">
- <title>Selecting a value</title>
- <programlisting><![CDATA[// get the height of all people with brown eyes
-CriteriaQuery<Integer> personCriteria = build.createQuery( Integer.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select( personRoot.get( Person.height ) );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Integer> heights = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-selectaggregation">
- <title>Selecting an aggregated value</title>
- <programlisting><![CDATA[// get the maximum height of all people with brown eyes
-CriteriaQuery<Integer> personCriteria = build.createQuery( Integer.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select( builder.max( personRoot.get( Person.height ) ) );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-Integer maxHeight = em.createQuery( personCriteria ).getSingleResult();]]></programlisting>
- </section>
- <section id="querycriteria-common-selecttuple">
- <title>Selecting a tuple</title>
- <programlisting><![CDATA[// get the id, height and gender of all people with brown eyes
-CriteriaQuery<Tuple> personCriteria = build.createTupleQuery();
-Root<Person> personRoot = personCriteria.from( Person.class );
-Path<Long> idPath = personRoot.get( Person_.id );
-idPath.setAlias( "id" );
-Path<Integer> heightPath = personRoot.get( Person_.height );
-Path<Gender> genderPath = personRoot.get( Person_.gender );
-personCriteria.multiselect( idPath, heightPath, genderPath );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Tuple> tuples = em.createQuery( personCriteria ).getResultList();
-for ( Tuple tuple : tuples ) {
- // the id value, for example, can be accessed by expression...
- handleId( tuple.get( idPath ) );
- // or by position...
- handleId( tuple.get( 0 ) );
- // or by the explicit alias we gave it...
- handleId( tuple.get( "id" ) );
-}]]></programlisting>
- </section>
- <section id="querycriteria-common-selectconstruct">
- <title>Selecting a constructed value</title>
- <programlisting><![CDATA[// get the id, height and gender of all people with brown eyes
-// like we did before, but this time wrap them in a "holder"
-CriteriaQuery<PersonHolder> personCriteria = build.createQuery( PersonHolder.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select(
- builder.construct(
- PersonHolder.class,
- personRoot.get( Person_.id ),
- personRoot.get( Person_.height ),
- personRoot.get( Person_.gender )
- )
-);
-List<PersonHolder> people = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-param">
+
+
+ <section id="querycriteria-param">
+ <title>Using parameters</title>
+ <example id="ex-querycriteria-param" >
<title>Using parameters</title>
- <programlisting><![CDATA[// get all people with brown eyes
-CriteriaQuery<Person> personCriteria = build.createQuery( Person.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select( personRoot );
+ <programlistingco>
+ <areaspec>
+ <area coords="4" id="ex.criteria.param.1"/>
+ <area coords="5" id="ex.criteria.param.2"/>
+ <area coords="7" id="ex.criteria.param.3"/>
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Person> criteria = build.createQuery( Person.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( personRoot );
ParameterExpression<String> eyeColorParam = builder.parameter( String.class );
-personCriteria.where( builder.equal( Person_.eyeColor, eyeColorParam ) );
-TypedQuery<Person> query = em.createQuery( personCriteria );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), eyeColorParam ) );
+TypedQuery<Person> query = em.createQuery( criteria );
query.setParameter( eyeColorParam, "brown" );
List<Person> people = query.getResultList();]]></programlisting>
- </section>
+ <calloutlist>
+ <callout arearefs="ex.criteria.param.1">
+ <para>
+ Use the <methodname>parameter</methodname> method of
+ <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ to obtain a parameter reference.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.param.2">
+ <para>
+ Use the parameter reference in the criteria query.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.param.3">
+ <para>
+ Use the parameter reference to bind the parameter value to the
+ <interfacename>javax.persistence.TypedQuery</interfacename>
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </example>
</section>
+
</chapter>
More information about the hibernate-commits
mailing list