HHH-4933 finish documentation on JPA 2 and EntityManager, migrate to jHighlight

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18956 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2010-03-10 10:56:16 +00:00
parent a284638d01
commit 3153fb385d
9 changed files with 309 additions and 142 deletions

View File

@ -70,6 +70,12 @@
<surname>Ebersole</surname> <surname>Ebersole</surname>
</author> </author>
<author>
<firstname>Gavin</firstname>
<surname>King</surname>
</author>
<!--TODO add translators like core did --> <!--TODO add translators like core did -->
</authorgroup> </authorgroup>
</bookinfo> </bookinfo>

View File

@ -1,4 +1,4 @@
<?xml version='1.0' encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
~ Hibernate, Relational Persistence for Idiomatic Java ~ Hibernate, Relational Persistence for Idiomatic Java
~ ~
@ -22,8 +22,8 @@
~ 51 Franklin Street, Fifth Floor ~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA ~ Boston, MA 02110-1301 USA
--> -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="batch"> <chapter id="batch">
<title>Batch processing</title> <title>Batch processing</title>
@ -34,7 +34,7 @@
Hibernate reference guide, however, EJB3 persistence differs Hibernate reference guide, however, EJB3 persistence differs
slightly.</para> slightly.</para>
<sect1 id="batch-direct"> <section id="batch-direct">
<title>Bulk update/delete</title> <title>Bulk update/delete</title>
<para>As already discussed, automatic and transparent object/relational <para>As already discussed, automatic and transparent object/relational
@ -44,7 +44,7 @@
directly in the database will not affect in-memory state. However, directly in the database will not affect in-memory state. However,
Hibernate provides methods for bulk SQL-style <literal>UPDATE</literal> Hibernate provides methods for bulk SQL-style <literal>UPDATE</literal>
and <literal>DELETE</literal> statement execution which are performed and <literal>DELETE</literal> statement execution which are performed
through EJB-QL (<xref linkend="queryhql" />).</para> through JP-QL (<xref linkend="queryhql" />).</para>
<para>The pseudo-syntax for <literal>UPDATE</literal> and <para>The pseudo-syntax for <literal>UPDATE</literal> and
<literal>DELETE</literal> statements is: <literal>( UPDATE | DELETE ) <literal>DELETE</literal> statements is: <literal>( UPDATE | DELETE )
@ -63,7 +63,7 @@
<listitem> <listitem>
<para>No joins (either implicit or explicit) can be specified in a <para>No joins (either implicit or explicit) can be specified in a
bulk EJB-QL query. Sub-queries may be used in the where-clause.</para> bulk JP-QL query. Sub-queries may be used in the where-clause.</para>
</listitem> </listitem>
<listitem> <listitem>
@ -71,26 +71,26 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>As an example, to execute an EJB-QL <literal>UPDATE</literal>, use <para>As an example, to execute an JP-QL <literal>UPDATE</literal>, use
the <literal>Query.executeUpdate()</literal> method:</para> the <literal>Query.executeUpdate()</literal> method:</para>
<programlisting>EntityManager entityManager = entityManagerFactory.createEntityManager(); <programlisting role="JAVA" language="JAVA">EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin(); entityManager.getTransaction().begin();
String ejbqlUpdate = "update Customer set name = :newName where name = :oldName" String jpqlUpdate = "update Customer set name = :newName where name = :oldName"
int updatedEntities = entityManager.createQuery( ejbqlUpdate ) int updatedEntities = entityManager.createQuery( jpqlUpdate )
.setParameter( "newName", newName ) .setParameter( "newName", newName )
.setParameter( "oldName", oldName ) .setParameter( "oldName", oldName )
.executeUpdate(); .executeUpdate();
entityManager.getTransaction().commit(); entityManager.getTransaction().commit();
entityManager.close();</programlisting> entityManager.close();</programlisting>
<para>To execute an EJB-QL <literal>DELETE</literal>, use the same <para>To execute an JP-QL <literal>DELETE</literal>, use the same
<literal>Query.executeUpdate()</literal> method (the method is named for <literal>Query.executeUpdate()</literal> method (the method is named for
those familiar with JDBC's those familiar with JDBC's
<literal>PreparedStatement.executeUpdate()</literal>):</para> <literal>PreparedStatement.executeUpdate()</literal>):</para>
<programlisting>EntityManager entityManager = entityManagerFactory.createEntityManager(); <programlisting role="JAVA" language="JAVA">EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin(); entityManager.getTransaction().begin();
String hqlDelete = "delete Customer where name = :oldName"; String hqlDelete = "delete Customer where name = :oldName";
@ -103,13 +103,13 @@ entityManager.close();</programlisting>
<para>The <literal>int</literal> value returned by the <para>The <literal>int</literal> value returned by the
<literal>Query.executeUpdate()</literal> method indicate the number of <literal>Query.executeUpdate()</literal> method indicate the number of
entities effected by the operation. This may or may not correlate with the entities effected by the operation. This may or may not correlate with the
number of rows effected in the database. An EJB-QL bulk operation might number of rows effected in the database. A JP-QL bulk operation might
result in multiple actual SQL statements being executed, for result in multiple actual SQL statements being executed, for
joined-subclass, for example. The returned number indicates the number of joined-subclass, for example. The returned number indicates the number of
actual entities affected by the statement. Going back to the example of actual entities affected by the statement. Going back to the example of
joined-subclass, a delete against one of the subclasses may actually joined-subclass, a delete against one of the subclasses may actually
result in deletes against not just the table to which that subclass is result in deletes against not just the table to which that subclass is
mapped, but also the "root" table and potentially joined-subclass tables mapped, but also the "root" table and potentially joined-subclass tables
further down the inheritence hierarchy.</para> further down the inheritance hierarchy.</para>
</sect1> </section>
</chapter> </chapter>

View File

@ -669,10 +669,10 @@ EntityManagerFactory programmaticEmf =
&lt;class&gt;org.hibernate.ejb.test.Distributor&lt;/class&gt; &lt;class&gt;org.hibernate.ejb.test.Distributor&lt;/class&gt;
&lt;class&gt;org.hibernate.ejb.test.Item&lt;/class&gt; &lt;class&gt;org.hibernate.ejb.test.Item&lt;/class&gt;
&lt;properties&gt; &lt;properties&gt;
&lt;property name="<literal>javax.persistence.jdbc.driver</literal>" value="org.hsqldb.jdbcDriver"/&gt; &lt;property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/&gt;
&lt;property name="<literal>javax.persistence.jdbc.user</literal>" value="sa"/&gt; &lt;property name="javax.persistence.jdbc.user" value="sa"/&gt;
&lt;property name="<literal>javax.persistence.jdbc.password</literal>" value=""/&gt; &lt;property name="javax.persistence.jdbc.password" value=""/&gt;
&lt;property name="<literal>javax.persistence.jdbc.url</literal>" value="jdbc:hsqldb:."/&gt; &lt;property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/&gt;
&lt;property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/ &lt;property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/
&lt;property name="hibernate.max_fetch_depth" value="3"/&gt; &lt;property name="hibernate.max_fetch_depth" value="3"/&gt;

View File

@ -74,7 +74,7 @@
<literal>new</literal> operator) it is in <literal>new</literal> state. <literal>new</literal> operator) it is in <literal>new</literal> state.
You can make it persistent by associating it to an entity manager:</para> You can make it persistent by associating it to an entity manager:</para>
<programlisting>DomesticCat fritz = new DomesticCat(); <programlisting language="JAVA" role="JAVA">DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER); fritz.setColor(Color.GINGER);
fritz.setSex('M'); fritz.setSex('M');
fritz.setName("Fritz"); fritz.setName("Fritz");
@ -93,7 +93,7 @@ em.persist(fritz);</programlisting>
<para>Load an entity instance by its identifier value with the entity <para>Load an entity instance by its identifier value with the entity
manager's <code>find()</code> method:</para> manager's <code>find()</code> method:</para>
<programlisting>cat = em.find(Cat.class, catId); <programlisting language="JAVA" role="JAVA">cat = em.find(Cat.class, catId);
// You may need to wrap the primitive identifiers // You may need to wrap the primitive identifiers
long catId = 1234; long catId = 1234;
@ -105,7 +105,7 @@ em.find( Cat.class, new Long(catId) );</programlisting>
useful to link a child to its parent without having to load the useful to link a child to its parent without having to load the
parent.</para> parent.</para>
<programlisting>child = new Child(); <programlisting language="JAVA" role="JAVA">child = new Child();
child.SetName("Henry"); child.SetName("Henry");
Parent parent = em.getReference(Parent.class, parentId); //no query to the DB Parent parent = em.getReference(Parent.class, parentId); //no query to the DB
child.setParent(parent); child.setParent(parent);
@ -118,7 +118,7 @@ em.persist(child);</programlisting>
refreshed unless you specify <literal>REFRESH</literal> as a cascade style refreshed unless you specify <literal>REFRESH</literal> as a cascade style
of any associations:</para> of any associations:</para>
<programlisting>em.persist(cat); <programlisting language="JAVA" role="JAVA">em.persist(cat);
em.flush(); // force the SQL insert and triggers to run em.flush(); // force the SQL insert and triggers to run
em.refresh(cat); //re-read the state (after the trigger executes)</programlisting> em.refresh(cat); //re-read the state (after the trigger executes)</programlisting>
</section> </section>
@ -145,7 +145,7 @@ em.refresh(cat); //re-read the state (after the trigger executes)</programlistin
the query. Queries are always created using the current entity the query. Queries are always created using the current entity
manager:</para> manager:</para>
<programlisting>List&lt;?&gt; cats = em.createQuery( <programlisting language="JAVA" role="JAVA">List&lt;?&gt; cats = em.createQuery(
"select cat from Cat as cat where cat.birthdate &lt; ?1") "select cat from Cat as cat where cat.birthdate &lt; ?1")
.setParameter(1, date, TemporalType.DATE) .setParameter(1, date, TemporalType.DATE)
.getResultList(); .getResultList();
@ -176,7 +176,7 @@ Cat mother = (Cat) em.createQuery(
type-safe approach is the Criteria API explained in <xref type-safe approach is the Criteria API explained in <xref
linkend="querycriteria" />.</para> linkend="querycriteria" />.</para>
<programlisting>CriteriaQuery&lt;Cat&gt; criteria = builder.createQuery( Cat.class ); <programlisting language="JAVA" role="JAVA">CriteriaQuery&lt;Cat&gt; criteria = builder.createQuery( Cat.class );
Root&lt;Cat&gt; cat = criteria.from( Cat.class ); Root&lt;Cat&gt; cat = criteria.from( Cat.class );
criteria.select( cat ); criteria.select( cat );
criteria.where( builder.lt( cat.get( Cat_.birthdate ), catDate ) ); criteria.where( builder.lt( cat.get( Cat_.birthdate ), catDate ) );
@ -186,7 +186,7 @@ List&lt;Cat&gt; cats = em.createQuery( criteria ).getResultList(); //notice no d
using JP-QL (note that it's not as type-safe as the compiler has to using JP-QL (note that it's not as type-safe as the compiler has to
trust you with the return type.</para> trust you with the return type.</para>
<programlisting>//No downcasting since we pass the return type <programlisting language="JAVA" role="JAVA">//No downcasting since we pass the return type
List&lt;Cat&gt; cats = em.createQuery( List&lt;Cat&gt; cats = em.createQuery(
"select cat from Cat as cat where cat.birthdate &lt; ?1", Cat.class) "select cat from Cat as cat where cat.birthdate &lt; ?1", Cat.class)
.setParameter(1, date, TemporalType.DATE) .setParameter(1, date, TemporalType.DATE)
@ -205,7 +205,7 @@ List&lt;Cat&gt; cats = em.createQuery(
<para>JPA queries can return tuples of objects if projection is used. <para>JPA queries can return tuples of objects if projection is used.
Each result tuple is returned as an object array:</para> Each result tuple is returned as an object array:</para>
<programlisting>Iterator kittensAndMothers = sess.createQuery( <programlisting language="JAVA" role="JAVA">Iterator kittensAndMothers = sess.createQuery(
"select kitten, mother from Cat kitten join kitten.mother mother") "select kitten, mother from Cat kitten join kitten.mother mother")
.getResultList() .getResultList()
.iterator(); .iterator();
@ -233,7 +233,7 @@ while ( kittensAndMothers.hasNext() ) {
persistent state (in other words, they are considered "read persistent state (in other words, they are considered "read
only"):</para> only"):</para>
<programlisting>Iterator results = em.createQuery( <programlisting language="JAVA" role="JAVA">Iterator results = em.createQuery(
"select cat.color, min(cat.birthdate), count(cat) from Cat cat " + "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
"group by cat.color") "group by cat.color")
.getResultList() .getResultList()
@ -258,7 +258,7 @@ while ( results.hasNext() ) {
in the query string. Named parameters should be preferred, they are in the query string. Named parameters should be preferred, they are
more robust and easier to read and understand:</para> more robust and easier to read and understand:</para>
<programlisting>// Named parameter (preferred) <programlisting language="JAVA" role="JAVA">// Named parameter (preferred)
Query q = em.createQuery("select cat from DomesticCat cat where cat.name = :name"); Query q = em.createQuery("select cat from DomesticCat cat where cat.name = :name");
q.setParameter("name", "Fritz"); q.setParameter("name", "Fritz");
List cats = q.getResultList(); List cats = q.getResultList();
@ -284,7 +284,7 @@ List cats = q.list();</programlisting>
number of rows you want to retrieve and/or the first row you want to number of rows you want to retrieve and/or the first row you want to
retrieve), use the following methods:</para> retrieve), use the following methods:</para>
<programlisting>Query q = em.createQuery("select cat from DomesticCat cat"); <programlisting language="JAVA" role="JAVA">Query q = em.createQuery("select cat from DomesticCat cat");
q.setFirstResult(20); q.setFirstResult(20);
q.setMaxResults(10); q.setMaxResults(10);
List cats = q.getResultList(); //return cats from the 20th position to 29th</programlisting> List cats = q.getResultList(); //return cats from the 20th position to 29th</programlisting>
@ -298,20 +298,20 @@ List cats = q.getResultList(); //return cats from the 20th position to 29th</pro
<para>You may also define named queries through annotations:</para> <para>You may also define named queries through annotations:</para>
<programlisting>@javax.persistence.NamedQuery(name="eg.DomesticCat.by.name.and.minimum.weight", <programlisting language="JAVA" role="JAVA">@javax.persistence.NamedQuery(name="eg.DomesticCat.by.name.and.minimum.weight",
query="select cat from eg.DomesticCat as cat where cat.name = ?1 and cat.weight &gt; ?2")</programlisting> query="select cat from eg.DomesticCat as cat where cat.name = ?1 and cat.weight &gt; ?2")</programlisting>
<para>Parameters are bound programmatically to the named query, before <para>Parameters are bound programmatically to the named query, before
it is executed:</para> it is executed:</para>
<programlisting>Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight"); <programlisting language="JAVA" role="JAVA">Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight");
q.setString(1, name); q.setString(1, name);
q.setInt(2, minWeight); q.setInt(2, minWeight);
List&lt;?&gt; cats = q.getResultList();</programlisting> List&lt;?&gt; cats = q.getResultList();</programlisting>
<para>You can also use the slightly more type-safe approach:</para> <para>You can also use the slightly more type-safe approach:</para>
<programlisting>Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight", Cat.class); <programlisting language="JAVA" role="JAVA">Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight", Cat.class);
q.setString(1, name); q.setString(1, name);
q.setInt(2, minWeight); q.setInt(2, minWeight);
List&lt;Cat&gt; cats = q.getResultList();</programlisting> List&lt;Cat&gt; cats = q.getResultList();</programlisting>
@ -335,7 +335,7 @@ List&lt;Cat&gt; cats = q.getResultList();</programlisting>
remember that all entity columns have to be returned for this remember that all entity columns have to be returned for this
mechanism to work):</para> mechanism to work):</para>
<programlisting>@SqlResultSetMapping(name="getItem", entities = <programlisting language="JAVA" role="JAVA">@SqlResultSetMapping(name="getItem", entities =
@EntityResult(entityClass=org.hibernate.ejb.test.Item.class, fields= { @EntityResult(entityClass=org.hibernate.ejb.test.Item.class, fields= {
@FieldResult(name="name", column="itemname"), @FieldResult(name="name", column="itemname"),
@FieldResult(name="descr", column="itemdescription") @FieldResult(name="descr", column="itemdescription")
@ -358,7 +358,7 @@ item = (Item) q.getSingleResult(); //from a class columns names match the mappin
<title>Query lock and flush mode</title> <title>Query lock and flush mode</title>
<para>You can adjust the flush mode used when executing the query as <para>You can adjust the flush mode used when executing the query as
well as define the lock mode used to load the entities. </para> well as define the lock mode used to load the entities.</para>
<para>Adjusting the flush mode is interesting when one must guaranty <para>Adjusting the flush mode is interesting when one must guaranty
that a query execution will not trigger a flush operation. Most of the that a query execution will not trigger a flush operation. Most of the
@ -367,7 +367,7 @@ item = (Item) q.getSingleResult(); //from a class columns names match the mappin
<para>Adjusting the lock mode is useful if you need to lock the <para>Adjusting the lock mode is useful if you need to lock the
objects returns by the query to a certain level.</para> objects returns by the query to a certain level.</para>
<programlisting>query.setFlushMode(FlushModeType.COMMIT) <programlisting language="JAVA" role="JAVA">query.setFlushMode(FlushModeType.COMMIT)
.setLockMode(LockModeType.PESSIMISTIC_READ);</programlisting> .setLockMode(LockModeType.PESSIMISTIC_READ);</programlisting>
<note> <note>
@ -492,7 +492,7 @@ item = (Item) q.getSingleResult(); //from a class columns names match the mappin
<methodname>find()</methodname> it, and then manipulate it directly, while <methodname>find()</methodname> it, and then manipulate it directly, while
the persistence context is open:</para> the persistence context is open:</para>
<programlisting>Cat cat = em.find( Cat.class, new Long(69) ); <programlisting language="JAVA" role="JAVA">Cat cat = em.find( Cat.class, new Long(69) );
cat.setName("PK"); cat.setName("PK");
em.flush(); // changes to cat are automatically detected and persisted</programlisting> em.flush(); // changes to cat are automatically detected and persisted</programlisting>
@ -510,7 +510,7 @@ em.flush(); // changes to cat are automatically detected and persisted</program
by Hibernate) by closing the EntityManager or in a more fine-grained by Hibernate) by closing the EntityManager or in a more fine-grained
approach by calling the <methodname>detach()</methodname> method.</para> approach by calling the <methodname>detach()</methodname> method.</para>
<programlisting>Cat cat = em.find( Cat.class, new Long(69) ); <programlisting language="JAVA" role="JAVA">Cat cat = em.find( Cat.class, new Long(69) );
... ...
em.detach(cat); em.detach(cat);
cat.setName("New name"); //not propatated to the database</programlisting> cat.setName("New name"); //not propatated to the database</programlisting>
@ -530,7 +530,7 @@ cat.setName("New name"); //not propatated to the database</programlisting>
for persistence of modifications made to detached instances using the for persistence of modifications made to detached instances using the
<methodname>EntityManager.merge()</methodname> method:</para> <methodname>EntityManager.merge()</methodname> method:</para>
<programlisting>// in the first entity manager <programlisting language="JAVA" role="JAVA">// in the first entity manager
Cat cat = firstEntityManager.find(Cat.class, catId); Cat cat = firstEntityManager.find(Cat.class, catId);
Cat potentialMate = new Cat(); Cat potentialMate = new Cat();
firstEntityManager.persist(potentialMate); firstEntityManager.persist(potentialMate);
@ -563,7 +563,7 @@ secondEntityManager.merge(mate); // update mate</programlisting>
not a detached instance) to <literal>merge()</literal>, the entity manager not a detached instance) to <literal>merge()</literal>, the entity manager
will figure this out for you:</para> will figure this out for you:</para>
<programlisting>// In the first entity manager <programlisting language="JAVA" role="JAVA">// In the first entity manager
Cat cat = firstEntityManager.find(Cat.class, catID); Cat cat = firstEntityManager.find(Cat.class, catID);
// In a higher layer of the application, detached // In a higher layer of the application, detached
@ -739,7 +739,7 @@ secondEntityManager.merge(mate); // save the new instance</programlisting>
automatically using the explained routine unless automatically using the explained routine unless
<methodname>flush()</methodname> is called explicitly.</para> <methodname>flush()</methodname> is called explicitly.</para>
<programlisting>em = emf.createEntityManager(); <programlisting language="JAVA" role="JAVA">em = emf.createEntityManager();
Transaction tx = em.getTransaction().begin(); Transaction tx = em.getTransaction().begin();
em.setFlushMode(FlushModeType.COMMIT); // allow queries to return stale state em.setFlushMode(FlushModeType.COMMIT); // allow queries to return stale state
@ -817,11 +817,11 @@ em.getTransaction().commit(); // flush occurs</programlisting>
associated entity (or collection of entities), you must indicate that in associated entity (or collection of entities), you must indicate that in
the association annotation:</para> the association annotation:</para>
<programlisting>@OneToOne(cascade=CascadeType.PERSIST)</programlisting> <programlisting language="JAVA" role="JAVA">@OneToOne(cascade=CascadeType.PERSIST)</programlisting>
<para>Cascading options can be combined:</para> <para>Cascading options can be combined:</para>
<programlisting>@OneToOne(cascade= { CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH } )</programlisting> <programlisting language="JAVA" role="JAVA">@OneToOne(cascade= { CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH } )</programlisting>
<para>You may even use <literal>CascadeType.ALL</literal> to specify that <para>You may even use <literal>CascadeType.ALL</literal> to specify that
all operations should be cascaded for a particular association. Remember all operations should be cascaded for a particular association. Remember
@ -924,4 +924,137 @@ em.getTransaction().commit(); // flush occurs</programlisting>
nobody changes the data underneath while pessimistic locks enforce the nobody changes the data underneath while pessimistic locks enforce the
lock right away and keep it till the transaction is committed.</para> lock right away and keep it till the transaction is committed.</para>
</section> </section>
<section>
<title>Caching</title>
<para>When the second-level cache is activated (see <xref
linkend="setup-configuration-packaging" /> and the Hibernate Annotations
reference documentation), Hibernate ensures it is used and properly
updated. You can however adjust these settings by passing two
properties:</para>
<itemizedlist>
<listitem>
<para><literal>javax.persistence.cache.retrieveMode</literal> which
accepts <literal><classname>CacheRetrieveMode</classname></literal>
values</para>
</listitem>
<listitem>
<para><literal>javax.persistence.cache.storeMode</literal> which
accepts <classname>CacheStoreMode</classname> values</para>
</listitem>
</itemizedlist>
<para><classname>CacheRetrieveMode</classname> controls how Hibernate
accesses information from the second-level cache: <literal>USE</literal>
which is the default or <literal>BYPASS</literal> which means ignore the
cache. <classname>CacheStoreMode</classname> controls how Hibernate pushes
information to the second-level cache: <literal>USE</literal> which is the
default and push data in the cache when reading from and writing to the
database, <literal>BYPASS</literal> which does not insert new data in the
cache (but can invalidate obsolete data) and
<classname>REFRESH</classname> which does like default but also force data
to be pushed to the cache on database read even if the data is already
cached.</para>
<para>You can set these properties:</para>
<itemizedlist>
<listitem>
<para>on a particular <classname>EntityManager</classname> via the
<methodname>setProperty</methodname> method</para>
</listitem>
<listitem>
<para>on a query via a query hint (<methodname>setHint</methodname>
method)</para>
</listitem>
<listitem>
<para>when calling <methodname>find()</methodname> and
<methodname>refresh()</methodname> and passing the properties in the
appropriate <classname>Map</classname></para>
</listitem>
</itemizedlist>
<para>JPA also introduces an API to interrogate the second-level cache and
evict data manually.</para>
<programlisting language="JAVA" role="JAVA">Cache cache = entityManagerFactory.getCache();
if ( cache.contains(User.class, userId) ) {
//load it as we don't hit the DB
}
cache.evict(User.class, userId); //manually evict user form the second-level cache
cache.evict(User.class); //evict all users from the second-level cache
cache.evictAll(); //purge the second-level cache entirely</programlisting>
</section>
<section>
<title>Checking the state of an object</title>
<para>You can check whether an object is managed by the persistence
context</para>
<programlisting language="JAVA" role="JAVA">entityManager.get(Cat.class, catId);
...
boolean isIn = entityManager.contains(cat);
assert isIn;</programlisting>
<para>You can also check whether an object, an association or a property
is lazy or not. You can do that independently of the underlying
persistence provider: </para>
<programlisting language="JAVA" role="JAVA">PersistenceUtil jpaUtil = Persistence.getPersistenceUtil();
if ( jpaUtil.isLoaded( customer.getAddress() ) {
//display address if loaded
}
if ( jpaUtil.isLoaded( customer.getOrders ) ) {
//display orders if loaded
}
if (jpaUtil.isLoaded(customer, "detailedBio") ) {
//display property detailedBio if loaded
}</programlisting>
<para>However, if you have access to the entityManagerFactory, we
recommend you to use:</para>
<programlisting language="JAVA" role="JAVA">PersistenceUnitUtil jpaUtil = entityManager.getEntityManagerFactory().getPersistenceUnitUtil();
Customer customer = entityManager.get( Customer.class, customerId );
if ( jpaUtil.isLoaded( customer.getAddress() ) {
//display address if loaded
}
if ( jpaUtil.isLoaded( customer.getOrders ) ) {
//display orders if loaded
}
if (jpaUtil.isLoaded(customer, "detailedBio") ) {
//display property detailedBio if loaded
}
log.debug( "Customer id {}", jpaUtil.getIdentifier(customer) );</programlisting>
<para>The performances are likely to be slightly better and you can get
the identifier value from an object (using
<methodname>getIdentifier()</methodname>).</para>
<note>
<para>These are roughly the counterpart methods of
<methodname>Hibernate.isInitialize</methodname>.</para>
</note>
</section>
<section>
<title>Native Hibernate API</title>
<para>You can always fall back to the underlying
<classname>Session</classname> API from a given
<classname>EntityManager</classname>:</para>
<programlisting language="JAVA" role="JAVA">Session session = entityManager.unwrap(Session.class);</programlisting>
</section>
</chapter> </chapter>

View File

@ -45,7 +45,7 @@
entity class with the <literal>@EntityListeners</literal> entity class with the <literal>@EntityListeners</literal>
annotation:</para> annotation:</para>
<programlisting>@Entity <programlisting role="JAVA" language="JAVA">@Entity
@EntityListeners(class=Audit.class) @EntityListeners(class=Audit.class)
public class Cat { public class Cat {
@Id private Integer id; @Id private Integer id;
@ -221,7 +221,7 @@ public class LastUpdateListener {
deployment descriptors. There is also an additional feature that can be deployment descriptors. There is also an additional feature that can be
useful: default event listeners.</para> useful: default event listeners.</para>
<programlisting>&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting role="XML" language="XML">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" &lt;entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

View File

@ -49,7 +49,7 @@
of the of the
<interfacename>javax.persistence.EntityManagerFactory</interfacename></para> <interfacename>javax.persistence.EntityManagerFactory</interfacename></para>
<programlisting>CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();</programlisting> <programlisting role="JAVA" language="JAVA">CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();</programlisting>
<para>The next step is to obtain a <para>The next step is to obtain a
<interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>. You <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>. You
@ -57,11 +57,11 @@
<interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename> <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
for this purpose.</para> for this purpose.</para>
<programlisting>CriteriaQuery&lt;T&gt; createQuery(Class&lt;T&gt;)</programlisting> <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;T&gt; createQuery(Class&lt;T&gt;)</programlisting>
<programlisting>CriteriaQuery&lt;Tuple&gt; createTupleQuery()</programlisting> <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Tuple&gt; createTupleQuery()</programlisting>
<programlisting>CriteriaQuery&lt;Object&gt; createQuery()</programlisting> <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Object&gt; createQuery()</programlisting>
<para>Each serves a different purpose depending on the expected type of the <para>Each serves a different purpose depending on the expected type of the
query results.</para> query results.</para>
@ -77,7 +77,7 @@
<section id="querycriteria-typedquery"> <section id="querycriteria-typedquery">
<title>Typed criteria queries</title> <title>Typed criteria queries</title>
<programlisting>CriteriaQuery&lt;T&gt; createQuery(Class&lt;T&gt;)</programlisting> <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;T&gt; createQuery(Class&lt;T&gt;)</programlisting>
<para>The type of the criteria query (aka the &lt;T&gt;) indicates the <para>The type of the criteria query (aka the &lt;T&gt;) indicates the
expected types in the query result. This might be an entity, an Integer, expected types in the query result. This might be an entity, an Integer,
@ -106,7 +106,7 @@
<area coords="4" id="ex.criteria.typedquery.entity.3" /> <area coords="4" id="ex.criteria.typedquery.entity.3" />
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Person&gt; criteria = builder.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; criteria = builder.createQuery( Person.class );
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
criteria.select( personRoot ); criteria.select( personRoot );
criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
@ -160,7 +160,7 @@ for ( Person person : people ) { ... }</programlisting>
<area coords="3" id="ex.criteria.typedquery.attr.2" /> <area coords="3" id="ex.criteria.typedquery.attr.2" />
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Integer&gt; criteria = builder.createQuery( Integer.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Integer&gt; criteria = builder.createQuery( Integer.class );
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
criteria.select( personRoot.get( Person_.age ) ); criteria.select( personRoot.get( Person_.age ) );
criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
@ -195,7 +195,7 @@ for ( Integer age : ages ) { ... } </programlisting>
<area coords="3" id="ex.criteria.typedquery.expr.1" /> <area coords="3" id="ex.criteria.typedquery.expr.1" />
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Integer&gt; criteria = builder.createQuery( Integer.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Integer&gt; criteria = builder.createQuery( Integer.class );
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
criteria.select( builder.max( personRoot.get( Person_.age ) ) ); criteria.select( builder.max( personRoot.get( Person_.age ) ) );
criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
@ -239,7 +239,7 @@ Integer maxAge = em.createQuery( criteria ).getSingleResult();</programlisting>
<area coords="5" id="ex.criteria.typedquery.array.2" /> <area coords="5" id="ex.criteria.typedquery.array.2" />
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Object[]&gt; criteria = builder.createQuery( Object[].class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Object[]&gt; criteria = builder.createQuery( Object[].class );
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
Path&lt;Long&gt; idPath = personRoot.get( Person_.id ); Path&lt;Long&gt; idPath = personRoot.get( Person_.id );
Path&lt;Integer&gt; agePath = personRoot.get( Person_.age ); Path&lt;Integer&gt; agePath = personRoot.get( Person_.age );
@ -284,7 +284,7 @@ for ( Object[] values : valueArray ) {
<area coords="5" id="ex.criteria.typedquery.array2.2" /> <area coords="5" id="ex.criteria.typedquery.array2.2" />
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Object[]&gt; criteria = builder.createQuery( Object[].class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Object[]&gt; criteria = builder.createQuery( Object[].class );
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
Path&lt;Long&gt; idPath = personRoot.get( Person_.id ); Path&lt;Long&gt; idPath = personRoot.get( Person_.id );
Path&lt;Integer&gt; agePath = personRoot.get( Person_.age ); Path&lt;Integer&gt; agePath = personRoot.get( Person_.age );
@ -351,7 +351,7 @@ for ( Object[] values : valueArray ) {
</areaset> </areaset>
</areaspec> </areaspec>
<programlisting>public class PersonWrapper { <programlisting role="JAVA" language="JAVA">public class PersonWrapper {
private final Long id; private final Long id;
private final Integer age; private final Integer age;
public PersonWrapper(Long id, Integer age) { public PersonWrapper(Long id, Integer age) {
@ -433,7 +433,7 @@ for ( PersonWrapper person : people ) { ... }</programlisting>
</areaset> </areaset>
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Tuple&gt; criteria = builder.createTupleQuery(); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Tuple&gt; criteria = builder.createTupleQuery();
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
Path&lt;Long&gt; idPath = personRoot.get( Person_.id ); Path&lt;Long&gt; idPath = personRoot.get( Person_.id );
Path&lt;Integer&gt; agePath = personRoot.get( Person_.age ); Path&lt;Integer&gt; agePath = personRoot.get( Person_.age );
@ -493,7 +493,7 @@ for ( Tuple tuple : valueArray ) {
<term>typed</term> <term>typed</term>
<listitem> <listitem>
<programlisting>&lt;X&gt; X get(TupleElement&lt;X&gt; tupleElement)</programlisting> <programlisting role="JAVA" language="JAVA">&lt;X&gt; X get(TupleElement&lt;X&gt; tupleElement)</programlisting>
<para>This allows typed access to the underlying tuple elements. <para>This allows typed access to the underlying tuple elements.
We see this in <xref linkend="ex-criteria-typedquery-tuple" /> in We see this in <xref linkend="ex-criteria-typedquery-tuple" /> in
@ -508,9 +508,9 @@ for ( Tuple tuple : valueArray ) {
<term>positional</term> <term>positional</term>
<listitem> <listitem>
<programlisting>Object get(int i)</programlisting> <programlisting role="JAVA" language="JAVA">Object get(int i)</programlisting>
<programlisting>&lt;X&gt; X get(int i, Class&lt;X&gt; type)</programlisting> <programlisting role="JAVA" language="JAVA">&lt;X&gt; X get(int i, Class&lt;X&gt; type)</programlisting>
<para>Very similar to what we saw in <xref <para>Very similar to what we saw in <xref
linkend="ex-criteria-typedquery-array" /> and <xref linkend="ex-criteria-typedquery-array" /> and <xref
@ -527,9 +527,9 @@ for ( Tuple tuple : valueArray ) {
<term>aliased</term> <term>aliased</term>
<listitem> <listitem>
<programlisting>Object get(String alias)</programlisting> <programlisting role="JAVA" language="JAVA">Object get(String alias)</programlisting>
<programlisting>&lt;X&gt; X get(String alias, Class&lt;X&gt; type)</programlisting> <programlisting role="JAVA" language="JAVA">&lt;X&gt; X get(String alias, Class&lt;X&gt; type)</programlisting>
<para>Again, only the second form here provides typing, because <para>Again, only the second form here provides typing, because
the user explicitly provides the typing on access. We have not the user explicitly provides the typing on access. We have not
@ -574,14 +574,14 @@ for ( Tuple tuple : valueArray ) {
<methodname>from</methodname> methods on <methodname>from</methodname> methods on
<interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>:</para> <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>:</para>
<programlisting>&lt;X&gt; Root&lt;X&gt; from(Class&lt;X&gt;)</programlisting> <programlisting role="JAVA" language="JAVA">&lt;X&gt; Root&lt;X&gt; from(Class&lt;X&gt;)</programlisting>
<programlisting>&lt;X&gt; Root&lt;X&gt; from(EntityType&lt;X&gt;)</programlisting> <programlisting role="JAVA" language="JAVA">&lt;X&gt; Root&lt;X&gt; from(EntityType&lt;X&gt;)</programlisting>
<example> <example>
<title>Adding a root</title> <title>Adding a root</title>
<programlisting>CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class );
// create and add the root // create and add the root
person.from( Person.class ); person.from( Person.class );
...</programlisting> ...</programlisting>
@ -593,7 +593,7 @@ person.from( Person.class );
product</ulink> between the newly added root and the others. Here is an product</ulink> between the newly added root and the others. Here is an
example matching all single men and all single women:</para> example matching all single men and all single women:</para>
<programlisting>CriteriaQuery query = builder.createQuery(); <programlisting role="JAVA" language="JAVA">CriteriaQuery query = builder.createQuery();
Root&lt;Person&gt; men = query.from( Person.class ); Root&lt;Person&gt; men = query.from( Person.class );
Root&lt;Person&gt; women = query.from( Person.class ); Root&lt;Person&gt; women = query.from( Person.class );
Predicate menRestriction = builder.and( Predicate menRestriction = builder.and(
@ -620,7 +620,7 @@ query.where( builder.and( menRestriction, womenRestriction ) );</programlisting>
<example id="criteria-join-singular"> <example id="criteria-join-singular">
<title>Example with Embedded and ManyToOne</title> <title>Example with Embedded and ManyToOne</title>
<programlisting>CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class );
Root&lt;Person&gt; personRoot = person.from( Person.class ); Root&lt;Person&gt; personRoot = person.from( Person.class );
// Person.address is an embedded attribute // Person.address is an embedded attribute
Join&lt;Person,Address&gt; personAddress = personRoot.join( Person_.address ); Join&lt;Person,Address&gt; personAddress = personRoot.join( Person_.address );
@ -632,7 +632,7 @@ Join&lt;Address,Country&gt; addressCountry = personAddress.join( Address_.countr
<example id="criteria-join-plural"> <example id="criteria-join-plural">
<title>Example with Collections</title> <title>Example with Collections</title>
<programlisting>CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class );
Root&lt;Person&gt; personRoot = person.from( Person.class ); Root&lt;Person&gt; personRoot = person.from( Person.class );
Join&lt;Person,Order&gt; orders = personRoot.join( Person_.orders ); Join&lt;Person,Order&gt; orders = personRoot.join( Person_.orders );
Join&lt;Order,LineItem&gt; orderLines = orders.join( Order_.lineItems ); Join&lt;Order,LineItem&gt; orderLines = orders.join( Order_.lineItems );
@ -652,7 +652,7 @@ Join&lt;Order,LineItem&gt; orderLines = orders.join( Order_.lineItems );
<example id="criteria-fetch-singular"> <example id="criteria-fetch-singular">
<title>Example with Embedded and ManyToOne</title> <title>Example with Embedded and ManyToOne</title>
<programlisting>CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class );
Root&lt;Person&gt; personRoot = person.from( Person.class ); Root&lt;Person&gt; personRoot = person.from( Person.class );
// Person.address is an embedded attribute // Person.address is an embedded attribute
Join&lt;Person,Address&gt; personAddress = personRoot.fetch( Person_.address ); Join&lt;Person,Address&gt; personAddress = personRoot.fetch( Person_.address );
@ -672,7 +672,7 @@ Join&lt;Address,Country&gt; addressCountry = personAddress.fetch( Address_.count
<example id="criteria-fetch-plural"> <example id="criteria-fetch-plural">
<title>Example with Collections</title> <title>Example with Collections</title>
<programlisting>CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; personCriteria = builder.createQuery( Person.class );
Root&lt;Person&gt; personRoot = person.from( Person.class ); Root&lt;Person&gt; personRoot = person.from( Person.class );
Join&lt;Person,Order&gt; orders = personRoot.fetch( Person_.orders ); Join&lt;Person,Order&gt; orders = personRoot.fetch( Person_.orders );
Join&lt;Order,LineItem&gt; orderLines = orders.fetch( Order_.lineItems ); Join&lt;Order,LineItem&gt; orderLines = orders.fetch( Order_.lineItems );
@ -704,7 +704,7 @@ Join&lt;Order,LineItem&gt; orderLines = orders.fetch( Order_.lineItems );
<area coords="7" id="ex.criteria.param.3" /> <area coords="7" id="ex.criteria.param.3" />
</areaspec> </areaspec>
<programlisting>CriteriaQuery&lt;Person&gt; criteria = build.createQuery( Person.class ); <programlisting role="JAVA" language="JAVA">CriteriaQuery&lt;Person&gt; criteria = build.createQuery( Person.class );
Root&lt;Person&gt; personRoot = criteria.from( Person.class ); Root&lt;Person&gt; personRoot = criteria.from( Person.class );
criteria.select( personRoot ); criteria.select( personRoot );
ParameterExpression&lt;String&gt; eyeColorParam = builder.parameter( String.class ); ParameterExpression&lt;String&gt; eyeColorParam = builder.parameter( String.class );

View File

@ -1,4 +1,4 @@
<?xml version='1.0' encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
~ Hibernate, Relational Persistence for Idiomatic Java ~ Hibernate, Relational Persistence for Idiomatic Java
~ ~
@ -22,18 +22,22 @@
~ 51 Franklin Street, Fifth Floor ~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA ~ Boston, MA 02110-1301 USA
--> -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="queryhql"> <chapter id="queryhql">
<title>EJB-QL: The Object Query Language</title> <title>JP-QL: The Object Query Language</title>
<para> <para>The Java Persistence Query Language (JP-QL) has been heavily inspired
EJB3-QL has been heavily inspired by HQL, the native Hibernate Query Language. Both by HQL, the native Hibernate Query Language. Both are therefore very close
are therefore very close to SQL, but portable and independent of the database schema. to SQL, but portable and independent of the database schema. People familiar
People familiar with HQL shouldn't have any problem using EJB-QL. Actually, you with HQL shouldn't have any problem using JP-QL. In fact HQL is a strict
use the same query API for EJB-QL and HQL queries. Portable EJB3 applications however superset of JP-QL and you use the same query API for both types of queries.
should stick to EJB-QL or similar vendor extensions are needed. Portable JPA applications however should stick to JP-QL.</para>
</para>
<note>
<para>For a type-safe approach to query, we highly recommend you to use
the Criteria query, see <xref linkend="querycriteria" />.</para>
</note>
<sect1 id="queryhql-casesensitivity"> <sect1 id="queryhql-casesensitivity">
<title>Case Sensitivity</title> <title>Case Sensitivity</title>
@ -45,7 +49,7 @@
<literal>org.hibernate.eg.Foo</literal> and <literal>foo.barSet</literal> <literal>org.hibernate.eg.Foo</literal> and <literal>foo.barSet</literal>
is not <literal>foo.BARSET</literal>.</para> is not <literal>foo.BARSET</literal>.</para>
<para>This manual uses lowercase EJBQL keywords. Some users find queries <para>This manual uses lowercase JP-QL keywords. Some users find queries
with uppercase keywords more readable, but we find this convention ugly with uppercase keywords more readable, but we find this convention ugly
when embedded in Java code.</para> when embedded in Java code.</para>
</sect1> </sect1>
@ -53,28 +57,28 @@
<sect1 id="queryhql-from"> <sect1 id="queryhql-from">
<title>The from clause</title> <title>The from clause</title>
<para>The simplest possible EJB-QL query is of the form:</para> <para>The simplest possible JP-QL query is of the form:</para>
<programlisting>select c from eg.Cat c</programlisting> <programlisting>select c from eg.Cat c</programlisting>
<para>which simply returns all instances of the class <para>which simply returns all instances of the class
<literal>eg.Cat</literal>. Unlike HQL, the select clause is not optional <literal>eg.Cat</literal>. Unlike HQL, the select clause is not optional
in EJB-QL. We don't usually need to qualify the class name, since the in JP-QL. We don't usually need to qualify the class name, since the
entity name defaults to the unqualified class name entity name defaults to the unqualified class name
(<literal>@Entity</literal>). So we almost always just write:</para> (<literal>@Entity</literal>). So we almost always just write:</para>
<programlisting>select c from Cat c</programlisting> <programlisting>select c from Cat c</programlisting>
<para>As you may have noticed you can assign aliases to classes, the <para>As you may have noticed you can assign aliases to classes, the
<literal>as</literal> keywork is optional. An alias allows you to refer <literal>as</literal> keywork is optional. An alias allows you to refer to
to <literal>Cat</literal> in other parts of the query.</para> <literal>Cat</literal> in other parts of the query.</para>
<programlisting>select cat from Cat as cat</programlisting> <programlisting>select cat from Cat as cat</programlisting>
<para>Multiple classes may appear, resulting in a cartesian product or <para>Multiple classes may appear, resulting in a cartesian product or
"cross" join.</para> "cross" join.</para>
<programlisting>select form, param from Formula as form, Parameter as param</programlisting> <programlisting>select from, param from Formula as form, Parameter as param</programlisting>
<para>It is considered good practice to name query aliases using an <para>It is considered good practice to name query aliases using an
initial lowercase, consistent with Java naming standards for local initial lowercase, consistent with Java naming standards for local
@ -116,9 +120,9 @@
<para>In addition, a "fetch" join allows associations or collections of <para>In addition, a "fetch" join allows associations or collections of
values to be initialized along with their parent objects, using a single values to be initialized along with their parent objects, using a single
select. This is particularly useful in the case of a collection. It select. This is particularly useful in the case of a collection. It
effectively overrides the fetching options in the associations and collection effectively overrides the fetching options in the associations and
mapping metadata. See the Performance chapter of the Hibernate reference guide collection mapping metadata. See the Performance chapter of the Hibernate
for more information.</para> reference guide for more information.</para>
<programlisting>select cat from Cat as cat <programlisting>select cat from Cat as cat
inner join fetch cat.mate inner join fetch cat.mate
@ -141,15 +145,12 @@
<literal>iterate()</literal>. Nor should <literal>fetch</literal> be used <literal>iterate()</literal>. Nor should <literal>fetch</literal> be used
together with <literal>setMaxResults()</literal> or together with <literal>setMaxResults()</literal> or
<literal>setFirstResult()</literal>. It is possible to create a cartesian <literal>setFirstResult()</literal>. It is possible to create a cartesian
product by join fetching more than one collection in a query (as in the example product by join fetching more than one collection in a query (as in the
above), be careful the result of this product isn't bigger than you expect. example above), be careful the result of this product isn't bigger than
Join fetching multiple collection roles also sometimes gives unexpected results for you expect. Join fetching multiple collection roles gives unexpected
bag mappings, so be careful about how you formulate your queries in this case.</para> results for bag mappings as it is impossible for Hibernate to
differentiate legit duplicates of a given bag from artificial duplicates
<para> created by the multi-table cartesian product.</para>
TODO: The last statement is useless and typical developer thinking, please elaborate.
The word "sometimes" should never appear in any technical documentation.
</para>
<para>If you are using property-level lazy fetching (with bytecode <para>If you are using property-level lazy fetching (with bytecode
instrumentation), it is possible to force Hibernate to fetch the lazy instrumentation), it is possible to force Hibernate to fetch the lazy
@ -200,7 +201,8 @@ from DomesticCat as mother
inner join mother.mate as mate inner join mother.mate as mate
left outer join mother.kittens as offspr</programlisting> left outer join mother.kittens as offspr</programlisting>
<para>or as an actual typesafe Java object,</para> <para>or as an actual type-safe Java object (often called a view
object),</para>
<programlisting>select new Family(mother, mate, offspr) <programlisting>select new Family(mother, mate, offspr)
from DomesticCat as mother from DomesticCat as mother
@ -254,7 +256,8 @@ from Cat cat</programlisting>
</itemizedlist> </itemizedlist>
<para>You may use arithmetic operators, concatenation, and recognized SQL <para>You may use arithmetic operators, concatenation, and recognized SQL
functions in the select clause (dpending on configured dialect, HQL specific feature):</para> functions in the select clause (dpending on configured dialect, HQL
specific feature):</para>
<programlisting>select cat.weight + sum(kitten.weight) <programlisting>select cat.weight + sum(kitten.weight)
from Cat cat from Cat cat
@ -281,7 +284,7 @@ select count(distinct cat.name), count(cat) from Cat cat</programlisting>
<para>returns instances not only of <literal>Cat</literal>, but also of <para>returns instances not only of <literal>Cat</literal>, but also of
subclasses like <literal>DomesticCat</literal>. Hibernate queries may name subclasses like <literal>DomesticCat</literal>. Hibernate queries may name
<emphasis>any</emphasis> Java class or interface in the <emphasis>any</emphasis> Java class or interface in the
<literal>from</literal> clause (portable EJB-QL queries should only name <literal>from</literal> clause (portable JP-QL queries should only name
mapped entities). The query will return instances of all persistent mapped entities). The query will return instances of all persistent
classes that extend that class or implement the interface. The following classes that extend that class or implement the interface. The following
query would return all persistent objects:</para> query would return all persistent objects:</para>
@ -342,7 +345,8 @@ where cat.mate = mate</programlisting>
<para>The special property (lowercase) <literal>id</literal> may be used <para>The special property (lowercase) <literal>id</literal> may be used
to reference the unique identifier of an object. (You may also use its to reference the unique identifier of an object. (You may also use its
mapped identifer property name.). Note that this keyword is specific to HQL.</para> mapped identifer property name.). Note that this keyword is specific to
HQL.</para>
<programlisting>select cat from Cat as cat where cat.id = 123 <programlisting>select cat from Cat as cat where cat.id = 123
@ -426,15 +430,21 @@ where log.item.class = 'Payment' and log.item.id = payment.id</programlisting>
of</literal></para> of</literal></para>
</listitem> </listitem>
<listitem>
<para><literal>exists</literal>, <literal>all</literal>,
<literal>any</literal>, <literal>some</literal> (taking
subqueries)</para>
</listitem>
<listitem> <listitem>
<para>"Simple" case, <literal>case ... when ... then ... else ... <para>"Simple" case, <literal>case ... when ... then ... else ...
end</literal>, and "searched" case, <literal>case when ... then ... end</literal>, and "searched" case, <literal>case when ... then ...
else ... end (specific to HQL)</literal></para> else ... end</literal></para>
</listitem> </listitem>
<listitem> <listitem>
<para>string concatenation <literal>...||...</literal> or <para>string concatenation <literal>...||...</literal> or
<literal>concat(...,...) (use concat() for portable EJB-QL <literal>concat(...,...) (use concat() for portable JP-QL
queries)</literal></para> queries)</literal></para>
</listitem> </listitem>
@ -452,9 +462,9 @@ where log.item.class = 'Payment' and log.item.id = payment.id</programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para>Any function or operator defined by EJB-QL 3.0: <para>Any function or operator: <literal>substring(), trim(), lower(),
<literal>substring(), trim(), lower(), upper(), length(), locate(), upper(), length(), locate(), abs(), sqrt(),
abs(), sqrt(), bit_length()</literal></para> bit_length()</literal></para>
</listitem> </listitem>
<listitem> <listitem>
@ -462,6 +472,13 @@ where log.item.class = 'Payment' and log.item.id = payment.id</programlisting>
<literal>nullif()</literal></para> <literal>nullif()</literal></para>
</listitem> </listitem>
<listitem>
<para><literal>TYPE ... in ...</literal>, where the first argument is
an identifier variable and the second argument is the subclass to
restrict polymorphism to (or a list of subclasses surrounded by
parenthesis)</para>
</listitem>
<listitem> <listitem>
<para><literal>cast(... as ...)</literal>, where the second argument <para><literal>cast(... as ...)</literal>, where the second argument
is the name of a Hibernate type, and <literal>extract(... from is the name of a Hibernate type, and <literal>extract(... from
@ -490,6 +507,11 @@ where log.item.class = 'Payment' and log.item.id = payment.id</programlisting>
<literal>'1970-01-01 10:00:01.0'</literal></para> <literal>'1970-01-01 10:00:01.0'</literal></para>
</listitem> </listitem>
<listitem>
<para>JDBC escape syntax for dates (dependent on your JDBC driver
support) (eg. <code>where date = {d '2008-12-31'}</code>)</para>
</listitem>
<listitem> <listitem>
<para>Java <literal>public static final</literal> constants <para>Java <literal>public static final</literal> constants
<literal>eg.Color.TABBY</literal></para> <literal>eg.Color.TABBY</literal></para>
@ -548,7 +570,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id</programlisting>
supported when passed the element or index set of a collection supported when passed the element or index set of a collection
(<literal>elements</literal> and <literal>indices</literal> functions) or (<literal>elements</literal> and <literal>indices</literal> functions) or
the result of a subquery (see below). While subqueries are supported by the result of a subquery (see below). While subqueries are supported by
EJB-QL, <literal>elements</literal> and <literal>indices</literal> are JP-QL, <literal>elements</literal> and <literal>indices</literal> are
specific HQL features.</para> specific HQL features.</para>
<programlisting>select mother from Cat as mother, Cat as kit <programlisting>select mother from Cat as mother, Cat as kit
@ -567,7 +589,13 @@ where p.name = some elements(list.names)</programlisting>
<literal>elements</literal>, <literal>indices</literal>, <literal>elements</literal>, <literal>indices</literal>,
<literal>minindex</literal>, <literal>maxindex</literal>, <literal>minindex</literal>, <literal>maxindex</literal>,
<literal>minelement</literal>, <literal>maxelement</literal> - may only be <literal>minelement</literal>, <literal>maxelement</literal> - may only be
used in the where clause in Hibernate3.</para> used in the where clause in Hibernate.</para>
<para>JP-QL lets you access the key or the value of a map by using the
<literal>KEY()</literal> and <literal>VALUE()</literal> operations (even
access the Entry object using <literal>ENTRY()</literal>)</para>
<programlisting>SELECT i.name, VALUE(p) FROM Item i JOIN i.photos p WHERE KEY(p) LIKE %egret</programlisting>
<para>In HQL, elements of indexed collections (arrays, lists, maps) may be <para>In HQL, elements of indexed collections (arrays, lists, maps) may be
referred to by index (in a where clause only):</para> referred to by index (in a where clause only):</para>
@ -687,7 +715,7 @@ order by count(kitten) asc, sum(kitten.weight) desc</programlisting>
<sect1 id="queryhql-subqueries"> <sect1 id="queryhql-subqueries">
<title>Subqueries</title> <title>Subqueries</title>
<para>For databases that support subselects, EJB-QL supports subqueries <para>For databases that support subselects, JP-QL supports subqueries
within queries. A subquery must be surrounded by parentheses (often by an within queries. A subquery must be surrounded by parentheses (often by an
SQL aggregate function call). Even correlated subqueries (subqueries that SQL aggregate function call). Even correlated subqueries (subqueries that
refer to an alias in the outer query) are allowed.</para> refer to an alias in the outer query) are allowed.</para>
@ -737,11 +765,11 @@ where not ( cat.name, cat.color ) in (
</sect1> </sect1>
<sect1 id="queryhql-examples"> <sect1 id="queryhql-examples">
<title>EJB-QL examples</title> <title>JP-QL examples</title>
<para>Hibernate queries can be quite powerful and complex. In fact, the <para>Hibernate queries can be quite powerful and complex. In fact, the
power of the query language is one of Hibernate's main selling points (and power of the query language is one of Hibernate's main selling points (and
now EJB-QL). Here are some example queries very similar to queries that I now JP-QL). Here are some example queries very similar to queries that I
used on a recent project. Note that most queries you will write are much used on a recent project. Note that most queries you will write are much
simpler than these!</para> simpler than these!</para>
@ -848,8 +876,8 @@ order by account.type.sortOrder, account.accountNumber, payment.dueDate</program
<sect1 id="queryhql-bulk"> <sect1 id="queryhql-bulk">
<title>Bulk UPDATE &amp; DELETE Statements</title> <title>Bulk UPDATE &amp; DELETE Statements</title>
<para>Hibernate now supports UPDATE and DELETE statements in HQL/EJB-QL. See <xref <para>Hibernate now supports UPDATE and DELETE statements in HQL/JP-QL.
linkend="batch-direct" /> for details.</para> See <xref linkend="batch-direct" /> for details.</para>
</sect1> </sect1>
<sect1 id="queryhql-tipstricks"> <sect1 id="queryhql-tipstricks">

View File

@ -1,4 +1,4 @@
<?xml version='1.0' encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
~ Hibernate, Relational Persistence for Idiomatic Java ~ Hibernate, Relational Persistence for Idiomatic Java
~ ~
@ -22,8 +22,8 @@
~ 51 Franklin Street, Fifth Floor ~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA ~ Boston, MA 02110-1301 USA
--> -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="query_native"> <chapter id="query_native">
<title>Native query</title> <title>Native query</title>
@ -31,7 +31,7 @@
database. This is useful if you want to utilize database specific features database. This is useful if you want to utilize database specific features
such as query hints or the CONNECT BY option in Oracle. It also provides a such as query hints or the CONNECT BY option in Oracle. It also provides a
clean migration path from a direct SQL/JDBC based application to Hibernate. clean migration path from a direct SQL/JDBC based application to Hibernate.
Note that Hibernate3 allows you to specify handwritten SQL (including stored Note that Hibernate allows you to specify handwritten SQL (including stored
procedures) for all create, update, delete, and load operations (please procedures) for all create, update, delete, and load operations (please
refer to the reference guide for more information.)</para> refer to the reference guide for more information.)</para>
@ -42,10 +42,10 @@
description will help the <literal>EntityManager</literal> to map your description will help the <literal>EntityManager</literal> to map your
columns onto entity properties. This is done using the columns onto entity properties. This is done using the
<literal>@SqlResultSetMapping</literal> annotation. Each <literal>@SqlResultSetMapping</literal> annotation. Each
<literal>@SqlResultSetMapping </literal>has a name wich is used when <literal>@SqlResultSetMapping </literal>has a name which is used when
creating a SQL query on <literal>EntityManager</literal>.</para> creating a SQL query on <literal>EntityManager</literal>.</para>
<programlisting>@SqlResultSetMapping(name="GetNightAndArea", entities={ <programlisting role="JAVA" language="JAVA">@SqlResultSetMapping(name="GetNightAndArea", entities={
@EntityResult(name="org.hibernate.test.annotations.query.Night", fields = { @EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
@FieldResult(name="id", column="nid"), @FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"), @FieldResult(name="duration", column="night_duration"),
@ -65,7 +65,7 @@
<para>You can also define scalar results and even mix entity results and <para>You can also define scalar results and even mix entity results and
scalar results</para> scalar results</para>
<programlisting>@SqlResultSetMapping(name="ScalarAndEntities", <programlisting role="JAVA" language="JAVA">@SqlResultSetMapping(name="ScalarAndEntities",
entities={ entities={
@EntityResult(name="org.hibernate.test.annotations.query.Night", fields = { @EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
@FieldResult(name="id", column="nid"), @FieldResult(name="id", column="nid"),
@ -103,7 +103,7 @@
third one (not yet supported by Hibernate entity manager), returns pure third one (not yet supported by Hibernate entity manager), returns pure
scalar results.</para> scalar results.</para>
<programlisting>String sqlQuery = "select night.id nid, night.night_duration, night.night_date, area.id aid, " <programlisting role="JAVA" language="JAVA">String sqlQuery = "select night.id nid, night.night_duration, night.night_date, area.id aid, "
+ "night.area_id, area.name from Night night, Area area where night.area_id = area.id " + "night.area_id, area.name from Night night, Area area where night.area_id = area.id "
+ "and night.night_duration &gt;= ?"; + "and night.night_duration &gt;= ?";
Query q = entityManager.createNativeQuery(sqlQuery, "GetNightAndArea"); Query q = entityManager.createNativeQuery(sqlQuery, "GetNightAndArea");
@ -113,7 +113,7 @@ q.getResultList();</programlisting>
<para>This native query returns nights and area based on the <para>This native query returns nights and area based on the
<literal>GetNightAndArea</literal> result set.</para> <literal>GetNightAndArea</literal> result set.</para>
<programlisting>String sqlQuery = "select * from tbl_spaceship where owner = ?"; <programlisting role="JAVA" language="JAVA">String sqlQuery = "select * from tbl_spaceship where owner = ?";
Query q = entityManager.createNativeQuery(sqlQuery, SpaceShip.class); Query q = entityManager.createNativeQuery(sqlQuery, SpaceShip.class);
q.setParameter( 1, "Han" ); q.setParameter( 1, "Han" );
q.getResultList();</programlisting> q.getResultList();</programlisting>
@ -125,11 +125,11 @@ q.getResultList();</programlisting>
<sect1> <sect1>
<title>Named queries</title> <title>Named queries</title>
<para>Native named queries share the same calling API than EJB-QL named <para>Native named queries share the same calling API than JP-QL named
queries. Your code doesn't need to know the difference between the two. queries. Your code doesn't need to know the difference between the two.
This is very useful for migration from SQL to EJB-QL:</para> This is very useful for migration from SQL to JP-QL:</para>
<programlisting>Query q = entityManager.createNamedQuery("getSeasonByNativeQuery"); <programlisting role="JAVA" language="JAVA">Query q = entityManager.createNamedQuery("getSeasonByNativeQuery");
q.setParameter( 1, name ); q.setParameter( 1, name );
Season season = (Season) q.getSingleResult();</programlisting> Season season = (Season) q.getSingleResult();</programlisting>
</sect1> </sect1>

View File

@ -418,7 +418,7 @@
mechanism behind the scenes. The common entity manager and transaction mechanism behind the scenes. The common entity manager and transaction
handling idiom looks like this:</para> handling idiom looks like this:</para>
<programlisting>// Non-managed environment idiom <programlisting role="JAVA" language="JAVA">// Non-managed environment idiom
EntityManager em = emf.createEntityManager(); EntityManager em = emf.createEntityManager();
EntityTransaction tx = null; EntityTransaction tx = null;
try { try {
@ -501,7 +501,7 @@ finally {
<para>If you use bean-managed transactions (BMT), the code will look <para>If you use bean-managed transactions (BMT), the code will look
like this:</para> like this:</para>
<programlisting>// BMT idiom <programlisting role="JAVA" language="JAVA">// BMT idiom
@Resource public UserTransaction utx; @Resource public UserTransaction utx;
@Resource public EntityManagerFactory factory; @Resource public EntityManagerFactory factory;
@ -554,13 +554,13 @@ finally {
<para>Our entity manager/transaction management idiom for CMT and EJB3 <para>Our entity manager/transaction management idiom for CMT and EJB3
container-use is reduced to this:</para> container-use is reduced to this:</para>
<programlisting>//CMT idiom through injection <programlisting role="JAVA" language="JAVA">//CMT idiom through injection
@PersistenceContext(name="sample") EntityManager em;</programlisting> @PersistenceContext(name="sample") EntityManager em;</programlisting>
<para>Or this if you use Java Context and Dependency Injection <para>Or this if you use Java Context and Dependency Injection
(CDI).</para> (CDI).</para>
<programlisting>@Inject EntityManager em;</programlisting> <programlisting role="JAVA" language="JAVA">@Inject EntityManager em;</programlisting>
<para>In other words, all you have to do in a managed environment is to <para>In other words, all you have to do in a managed environment is to
inject the <literal>EntityManager</literal>, do your data access work, inject the <literal>EntityManager</literal>, do your data access work,
@ -834,7 +834,7 @@ finally {
the least efficient in terms of database access. It is the approach most the least efficient in terms of database access. It is the approach most
similar to EJB2 entities:</para> similar to EJB2 entities:</para>
<programlisting>// foo is an instance loaded by a previous entity manager <programlisting role="JAVA" language="JAVA">// foo is an instance loaded by a previous entity manager
em = factory.createEntityManager(); em = factory.createEntityManager();
EntityTransaction t = em.getTransaction(); EntityTransaction t = em.getTransaction();
t.begin(); t.begin();
@ -895,7 +895,7 @@ em.close();</programlisting>
performance impact. The following examples show the idiom in a performance impact. The following examples show the idiom in a
non-managed environment:</para> non-managed environment:</para>
<programlisting>// foo is an instance loaded earlier by the extended entity manager <programlisting role="JAVA" language="JAVA">// foo is an instance loaded earlier by the extended entity manager
em.getTransaction.begin(); // new connection to data store is obtained and tx started em.getTransaction.begin(); // new connection to data store is obtained and tx started
foo.setProperty("bar"); foo.setProperty("bar");
em.getTransaction().commit(); // End tx, flush and check version, disconnect</programlisting> em.getTransaction().commit(); // End tx, flush and check version, disconnect</programlisting>
@ -936,7 +936,7 @@ em.getTransaction().commit(); // End tx, flush and check version, disconnect</p
persistence context and then merges the changes using persistence context and then merges the changes using
<literal>EntityManager.merge()</literal>:</para> <literal>EntityManager.merge()</literal>:</para>
<programlisting>// foo is an instance loaded by a non-extended entity manager <programlisting role="JAVA" language="JAVA">// foo is an instance loaded by a non-extended entity manager
foo.setProperty("bar"); foo.setProperty("bar");
entityManager = factory.createEntityManager(); entityManager = factory.createEntityManager();
entityManager.getTransaction().begin(); entityManager.getTransaction().begin();