diff --git a/entitymanager/src/main/docbook/en/master.xml b/entitymanager/src/main/docbook/en/master.xml
index c999742549..3a104e2472 100644
--- a/entitymanager/src/main/docbook/en/master.xml
+++ b/entitymanager/src/main/docbook/en/master.xml
@@ -70,6 +70,12 @@
Ebersole
+
+ Gavin
+
+ King
+
+
diff --git a/entitymanager/src/main/docbook/en/modules/batch.xml b/entitymanager/src/main/docbook/en/modules/batch.xml
index 1ac359249e..02a7a5ae71 100644
--- a/entitymanager/src/main/docbook/en/modules/batch.xml
+++ b/entitymanager/src/main/docbook/en/modules/batch.xml
@@ -1,4 +1,4 @@
-
+
-
-
+
Batch processing
@@ -34,7 +34,7 @@
Hibernate reference guide, however, EJB3 persistence differs
slightly.
-
+
Bulk update/delete
As already discussed, automatic and transparent object/relational
@@ -44,7 +44,7 @@
directly in the database will not affect in-memory state. However,
Hibernate provides methods for bulk SQL-style UPDATE
and DELETE statement execution which are performed
- through EJB-QL ().
+ through JP-QL ().
The pseudo-syntax for UPDATE and
DELETE statements is: ( UPDATE | DELETE )
@@ -63,7 +63,7 @@
No joins (either implicit or explicit) can be specified in a
- bulk EJB-QL query. Sub-queries may be used in the where-clause.
+ bulk JP-QL query. Sub-queries may be used in the where-clause.
@@ -71,26 +71,26 @@
- As an example, to execute an EJB-QL UPDATE, use
+ As an example, to execute an JP-QL UPDATE, use
the Query.executeUpdate() method:
- EntityManager entityManager = entityManagerFactory.createEntityManager();
+ EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
-String ejbqlUpdate = "update Customer set name = :newName where name = :oldName"
-int updatedEntities = entityManager.createQuery( ejbqlUpdate )
+String jpqlUpdate = "update Customer set name = :newName where name = :oldName"
+int updatedEntities = entityManager.createQuery( jpqlUpdate )
.setParameter( "newName", newName )
.setParameter( "oldName", oldName )
.executeUpdate();
entityManager.getTransaction().commit();
entityManager.close();
- To execute an EJB-QL DELETE, use the same
+ To execute an JP-QL DELETE, use the same
Query.executeUpdate() method (the method is named for
those familiar with JDBC's
PreparedStatement.executeUpdate()):
- EntityManager entityManager = entityManagerFactory.createEntityManager();
+ EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
String hqlDelete = "delete Customer where name = :oldName";
@@ -103,13 +103,13 @@ entityManager.close();
The int value returned by the
Query.executeUpdate() method indicate the number of
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
joined-subclass, for example. The returned number indicates the number of
actual entities affected by the statement. Going back to the example of
joined-subclass, a delete against one of the subclasses may actually
result in deletes against not just the table to which that subclass is
mapped, but also the "root" table and potentially joined-subclass tables
- further down the inheritence hierarchy.
-
-
\ No newline at end of file
+ further down the inheritance hierarchy.
+
+
diff --git a/entitymanager/src/main/docbook/en/modules/configuration.xml b/entitymanager/src/main/docbook/en/modules/configuration.xml
index c52aa8c925..8ed6743f1e 100644
--- a/entitymanager/src/main/docbook/en/modules/configuration.xml
+++ b/entitymanager/src/main/docbook/en/modules/configuration.xml
@@ -669,10 +669,10 @@ EntityManagerFactory programmaticEmf =
<class>org.hibernate.ejb.test.Distributor</class>
<class>org.hibernate.ejb.test.Item</class>
<properties>
- <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
- <property name="javax.persistence.jdbc.user" value="sa"/>
- <property name="javax.persistence.jdbc.password" value=""/>
- <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
+ <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
+ <property name="javax.persistence.jdbc.user" value="sa"/>
+ <property name="javax.persistence.jdbc.password" value=""/>
+ <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/
<property name="hibernate.max_fetch_depth" value="3"/>
@@ -857,7 +857,7 @@ EntityManagerFactory emf =
Persistence class is bootstrap class to create an
entity manager factory.
- // Use persistence.xml configuration
+ // Use persistence.xml configuration
EntityManagerFactory emf = Persistence.createEntityManagerFactory("manager1")
EntityManager em = emf.createEntityManager(); // Retrieve an application managed entity manager
// Work with the EM
diff --git a/entitymanager/src/main/docbook/en/modules/entitymanagerapi.xml b/entitymanager/src/main/docbook/en/modules/entitymanagerapi.xml
index 4644640ae1..f62ee7017f 100644
--- a/entitymanager/src/main/docbook/en/modules/entitymanagerapi.xml
+++ b/entitymanager/src/main/docbook/en/modules/entitymanagerapi.xml
@@ -74,7 +74,7 @@
new operator) it is in new state.
You can make it persistent by associating it to an entity manager:
- DomesticCat fritz = new DomesticCat();
+ DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
@@ -93,7 +93,7 @@ em.persist(fritz);
Load an entity instance by its identifier value with the entity
manager's find()
method:
- cat = em.find(Cat.class, catId);
+ cat = em.find(Cat.class, catId);
// You may need to wrap the primitive identifiers
long catId = 1234;
@@ -105,7 +105,7 @@ em.find( Cat.class, new Long(catId) );
useful to link a child to its parent without having to load the
parent.
- child = new Child();
+ child = new Child();
child.SetName("Henry");
Parent parent = em.getReference(Parent.class, parentId); //no query to the DB
child.setParent(parent);
@@ -118,7 +118,7 @@ em.persist(child);
refreshed unless you specify REFRESH as a cascade style
of any associations:
- em.persist(cat);
+ em.persist(cat);
em.flush(); // force the SQL insert and triggers to run
em.refresh(cat); //re-read the state (after the trigger executes)
@@ -145,7 +145,7 @@ em.refresh(cat); //re-read the state (after the trigger executes)
- List<?> cats = em.createQuery(
+ List<?> cats = em.createQuery(
"select cat from Cat as cat where cat.birthdate < ?1")
.setParameter(1, date, TemporalType.DATE)
.getResultList();
@@ -176,7 +176,7 @@ Cat mother = (Cat) em.createQuery(
type-safe approach is the Criteria API explained in .
- CriteriaQuery<Cat> criteria = builder.createQuery( Cat.class );
+ CriteriaQuery<Cat> criteria = builder.createQuery( Cat.class );
Root<Cat> cat = criteria.from( Cat.class );
criteria.select( cat );
criteria.where( builder.lt( cat.get( Cat_.birthdate ), catDate ) );
@@ -186,7 +186,7 @@ List<Cat> cats = em.createQuery( criteria ).getResultList(); //notice no d
using JP-QL (note that it's not as type-safe as the compiler has to
trust you with the return type.
- //No downcasting since we pass the return type
+ //No downcasting since we pass the return type
List<Cat> cats = em.createQuery(
"select cat from Cat as cat where cat.birthdate < ?1", Cat.class)
.setParameter(1, date, TemporalType.DATE)
@@ -205,7 +205,7 @@ List<Cat> cats = em.createQuery(
JPA queries can return tuples of objects if projection is used.
Each result tuple is returned as an object array:
- Iterator kittensAndMothers = sess.createQuery(
+ Iterator kittensAndMothers = sess.createQuery(
"select kitten, mother from Cat kitten join kitten.mother mother")
.getResultList()
.iterator();
@@ -233,7 +233,7 @@ while ( kittensAndMothers.hasNext() ) {
persistent state (in other words, they are considered "read
only"):
- Iterator results = em.createQuery(
+ Iterator results = em.createQuery(
"select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
"group by cat.color")
.getResultList()
@@ -258,7 +258,7 @@ while ( results.hasNext() ) {
in the query string. Named parameters should be preferred, they are
more robust and easier to read and understand:
- // Named parameter (preferred)
+ // Named parameter (preferred)
Query q = em.createQuery("select cat from DomesticCat cat where cat.name = :name");
q.setParameter("name", "Fritz");
List cats = q.getResultList();
@@ -284,7 +284,7 @@ List cats = q.list();
number of rows you want to retrieve and/or the first row you want to
retrieve), use the following methods:
- Query q = em.createQuery("select cat from DomesticCat cat");
+ Query q = em.createQuery("select cat from DomesticCat cat");
q.setFirstResult(20);
q.setMaxResults(10);
List cats = q.getResultList(); //return cats from the 20th position to 29th
@@ -298,20 +298,20 @@ List cats = q.getResultList(); //return cats from the 20th position to 29thYou may also define named queries through annotations:
- @javax.persistence.NamedQuery(name="eg.DomesticCat.by.name.and.minimum.weight",
+ @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 > ?2")
Parameters are bound programmatically to the named query, before
it is executed:
- Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight");
+ Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight");
q.setString(1, name);
q.setInt(2, minWeight);
List<?> cats = q.getResultList();
You can also use the slightly more type-safe approach:
- Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight", Cat.class);
+ Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight", Cat.class);
q.setString(1, name);
q.setInt(2, minWeight);
List<Cat> cats = q.getResultList();
@@ -335,7 +335,7 @@ List<Cat> cats = q.getResultList();
remember that all entity columns have to be returned for this
mechanism to work):
- @SqlResultSetMapping(name="getItem", entities =
+ @SqlResultSetMapping(name="getItem", entities =
@EntityResult(entityClass=org.hibernate.ejb.test.Item.class, fields= {
@FieldResult(name="name", column="itemname"),
@FieldResult(name="descr", column="itemdescription")
@@ -358,7 +358,7 @@ item = (Item) q.getSingleResult(); //from a class columns names match the mappin
Query lock and flush mode
You can adjust the flush mode used when executing the query as
- well as define the lock mode used to load the entities.
+ well as define the lock mode used to load the entities.
Adjusting the flush mode is interesting when one must guaranty
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
Adjusting the lock mode is useful if you need to lock the
objects returns by the query to a certain level.
- query.setFlushMode(FlushModeType.COMMIT)
+ query.setFlushMode(FlushModeType.COMMIT)
.setLockMode(LockModeType.PESSIMISTIC_READ);
@@ -492,7 +492,7 @@ item = (Item) q.getSingleResult(); //from a class columns names match the mappin
find() it, and then manipulate it directly, while
the persistence context is open:
- Cat cat = em.find( Cat.class, new Long(69) );
+ Cat cat = em.find( Cat.class, new Long(69) );
cat.setName("PK");
em.flush(); // changes to cat are automatically detected and persisted
@@ -510,7 +510,7 @@ em.flush(); // changes to cat are automatically detected and persisteddetach() method.
- Cat cat = em.find( Cat.class, new Long(69) );
+ Cat cat = em.find( Cat.class, new Long(69) );
...
em.detach(cat);
cat.setName("New name"); //not propatated to the database
@@ -530,7 +530,7 @@ cat.setName("New name"); //not propatated to the database
for persistence of modifications made to detached instances using the
EntityManager.merge() method:
- // in the first entity manager
+ // in the first entity manager
Cat cat = firstEntityManager.find(Cat.class, catId);
Cat potentialMate = new Cat();
firstEntityManager.persist(potentialMate);
@@ -563,7 +563,7 @@ secondEntityManager.merge(mate); // update mate
not a detached instance) to merge(), the entity manager
will figure this out for you:
- // In the first entity manager
+ // In the first entity manager
Cat cat = firstEntityManager.find(Cat.class, catID);
// In a higher layer of the application, detached
@@ -739,7 +739,7 @@ secondEntityManager.merge(mate); // save the new instance
automatically using the explained routine unless
flush() is called explicitly.
- em = emf.createEntityManager();
+ em = emf.createEntityManager();
Transaction tx = em.getTransaction().begin();
em.setFlushMode(FlushModeType.COMMIT); // allow queries to return stale state
@@ -817,11 +817,11 @@ em.getTransaction().commit(); // flush occurs
associated entity (or collection of entities), you must indicate that in
the association annotation:
- @OneToOne(cascade=CascadeType.PERSIST)
+ @OneToOne(cascade=CascadeType.PERSIST)
Cascading options can be combined:
- @OneToOne(cascade= { CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH } )
+ @OneToOne(cascade= { CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH } )
You may even use CascadeType.ALL to specify that
all operations should be cascaded for a particular association. Remember
@@ -924,4 +924,137 @@ em.getTransaction().commit(); // flush occurs
nobody changes the data underneath while pessimistic locks enforce the
lock right away and keep it till the transaction is committed.
+
+
+ Caching
+
+ When the second-level cache is activated (see and the Hibernate Annotations
+ reference documentation), Hibernate ensures it is used and properly
+ updated. You can however adjust these settings by passing two
+ properties:
+
+
+
+ javax.persistence.cache.retrieveMode which
+ accepts CacheRetrieveMode
+ values
+
+
+
+ javax.persistence.cache.storeMode which
+ accepts CacheStoreMode values
+
+
+
+ CacheRetrieveMode controls how Hibernate
+ accesses information from the second-level cache: USE
+ which is the default or BYPASS which means ignore the
+ cache. CacheStoreMode controls how Hibernate pushes
+ information to the second-level cache: USE which is the
+ default and push data in the cache when reading from and writing to the
+ database, BYPASS which does not insert new data in the
+ cache (but can invalidate obsolete data) and
+ REFRESH which does like default but also force data
+ to be pushed to the cache on database read even if the data is already
+ cached.
+
+ You can set these properties:
+
+
+
+ on a particular EntityManager via the
+ setProperty method
+
+
+
+ on a query via a query hint (setHint
+ method)
+
+
+
+ when calling find() and
+ refresh() and passing the properties in the
+ appropriate Map
+
+
+
+ JPA also introduces an API to interrogate the second-level cache and
+ evict data manually.
+
+ 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
+
+
+
+ Checking the state of an object
+
+ You can check whether an object is managed by the persistence
+ context
+
+ entityManager.get(Cat.class, catId);
+...
+boolean isIn = entityManager.contains(cat);
+assert isIn;
+
+ 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:
+
+ 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
+}
+
+ However, if you have access to the entityManagerFactory, we
+ recommend you to use:
+
+ 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) );
+
+ The performances are likely to be slightly better and you can get
+ the identifier value from an object (using
+ getIdentifier()).
+
+
+ These are roughly the counterpart methods of
+ Hibernate.isInitialize.
+
+
+
+
+ Native Hibernate API
+
+ You can always fall back to the underlying
+ Session API from a given
+ EntityManager:
+
+ Session session = entityManager.unwrap(Session.class);
+
diff --git a/entitymanager/src/main/docbook/en/modules/listeners.xml b/entitymanager/src/main/docbook/en/modules/listeners.xml
index ea18046301..2d3c5b1772 100644
--- a/entitymanager/src/main/docbook/en/modules/listeners.xml
+++ b/entitymanager/src/main/docbook/en/modules/listeners.xml
@@ -45,7 +45,7 @@
entity class with the @EntityListeners
annotation:
- @Entity
+ @Entity
@EntityListeners(class=Audit.class)
public class Cat {
@Id private Integer id;
@@ -221,7 +221,7 @@ public class LastUpdateListener {
deployment descriptors. There is also an additional feature that can be
useful: default event listeners.
- <?xml version="1.0" encoding="UTF-8"?>
+ <?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diff --git a/entitymanager/src/main/docbook/en/modules/query_criteria.xml b/entitymanager/src/main/docbook/en/modules/query_criteria.xml
index c6e3edc927..01cddd5f39 100644
--- a/entitymanager/src/main/docbook/en/modules/query_criteria.xml
+++ b/entitymanager/src/main/docbook/en/modules/query_criteria.xml
@@ -49,7 +49,7 @@
of the
javax.persistence.EntityManagerFactory
- CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();
+ CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();
The next step is to obtain a
javax.persistence.criteria.CriteriaQuery. You
@@ -57,11 +57,11 @@
javax.persistence.criteria.CriteriaBuilder
for this purpose.
- CriteriaQuery<T> createQuery(Class<T>)
+ CriteriaQuery<T> createQuery(Class<T>)
- CriteriaQuery<Tuple> createTupleQuery()
+ CriteriaQuery<Tuple> createTupleQuery()
- CriteriaQuery<Object> createQuery()
+ CriteriaQuery<Object> createQuery()
Each serves a different purpose depending on the expected type of the
query results.
@@ -77,7 +77,7 @@
Typed criteria queries
- CriteriaQuery<T> createQuery(Class<T>)
+ CriteriaQuery<T> createQuery(Class<T>)
The type of the criteria query (aka the <T>) indicates the
expected types in the query result. This might be an entity, an Integer,
@@ -106,7 +106,7 @@
- CriteriaQuery<Person> criteria = builder.createQuery( Person.class );
+ 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" ) );
@@ -160,7 +160,7 @@ for ( Person person : people ) { ... }
- CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
+ 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" ) );
@@ -195,7 +195,7 @@ for ( Integer age : ages ) { ... }
- CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
+ 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" ) );
@@ -239,7 +239,7 @@ Integer maxAge = em.createQuery( criteria ).getSingleResult();
- CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
+ 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 );
@@ -284,7 +284,7 @@ for ( Object[] values : valueArray ) {
- CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
+ 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 );
@@ -351,7 +351,7 @@ for ( Object[] values : valueArray ) {
- public class PersonWrapper {
+ public class PersonWrapper {
private final Long id;
private final Integer age;
public PersonWrapper(Long id, Integer age) {
@@ -433,7 +433,7 @@ for ( PersonWrapper person : people ) { ... }
- CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
+ 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 );
@@ -493,7 +493,7 @@ for ( Tuple tuple : valueArray ) {
typed
- <X> X get(TupleElement<X> tupleElement)
+ <X> X get(TupleElement<X> tupleElement)
This allows typed access to the underlying tuple elements.
We see this in in
@@ -508,9 +508,9 @@ for ( Tuple tuple : valueArray ) {
positional
- Object get(int i)
+ Object get(int i)
- <X> X get(int i, Class<X> type)
+ <X> X get(int i, Class<X> type)
Very similar to what we saw in and aliased
- Object get(String alias)
+ Object get(String alias)
- <X> X get(String alias, Class<X> type)
+ <X> X get(String alias, Class<X> type)
Again, only the second form here provides typing, because
the user explicitly provides the typing on access. We have not
@@ -574,14 +574,14 @@ for ( Tuple tuple : valueArray ) {
from methods on
javax.persistence.criteria.CriteriaQuery:
- <X> Root<X> from(Class<X>)
+ <X> Root<X> from(Class<X>)
- <X> Root<X> from(EntityType<X>)
+ <X> Root<X> from(EntityType<X>)
Adding a root
- CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+ CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
// create and add the root
person.from( Person.class );
...
@@ -593,7 +593,7 @@ person.from( Person.class );
product between the newly added root and the others. Here is an
example matching all single men and all single women:
- CriteriaQuery query = builder.createQuery();
+ CriteriaQuery query = builder.createQuery();
Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
@@ -620,7 +620,7 @@ query.where( builder.and( menRestriction, womenRestriction ) );
Example with Embedded and ManyToOne
- CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+ 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.join( Person_.address );
@@ -632,7 +632,7 @@ Join<Address,Country> addressCountry = personAddress.join( Address_.countr
Example with Collections
- CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+ 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 );
@@ -652,7 +652,7 @@ Join<Order,LineItem> orderLines = orders.join( Order_.lineItems );
Example with Embedded and ManyToOne
- CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+ 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 );
@@ -672,7 +672,7 @@ Join<Address,Country> addressCountry = personAddress.fetch( Address_.count
Example with Collections
- CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+ 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 );
@@ -704,7 +704,7 @@ Join<Order,LineItem> orderLines = orders.fetch( Order_.lineItems );
- CriteriaQuery<Person> criteria = build.createQuery( Person.class );
+ CriteriaQuery<Person> criteria = build.createQuery( Person.class );
Root<Person> personRoot = criteria.from( Person.class );
criteria.select( personRoot );
ParameterExpression<String> eyeColorParam = builder.parameter( String.class );
diff --git a/entitymanager/src/main/docbook/en/modules/query_ejbql.xml b/entitymanager/src/main/docbook/en/modules/query_ejbql.xml
index 4b9570f765..336626ead1 100644
--- a/entitymanager/src/main/docbook/en/modules/query_ejbql.xml
+++ b/entitymanager/src/main/docbook/en/modules/query_ejbql.xml
@@ -1,4 +1,4 @@
-
+
-
-
+
- EJB-QL: The Object Query Language
+ JP-QL: The Object Query Language
-
- EJB3-QL has been heavily inspired by HQL, the native Hibernate Query Language. Both
- are therefore very close to SQL, but portable and independent of the database schema.
- People familiar with HQL shouldn't have any problem using EJB-QL. Actually, you
- use the same query API for EJB-QL and HQL queries. Portable EJB3 applications however
- should stick to EJB-QL or similar vendor extensions are needed.
-
+ The Java Persistence Query Language (JP-QL) has been heavily inspired
+ by HQL, the native Hibernate Query Language. Both are therefore very close
+ to SQL, but portable and independent of the database schema. People familiar
+ with HQL shouldn't have any problem using JP-QL. In fact HQL is a strict
+ superset of JP-QL and you use the same query API for both types of queries.
+ Portable JPA applications however should stick to JP-QL.
+
+
+ For a type-safe approach to query, we highly recommend you to use
+ the Criteria query, see .
+
Case Sensitivity
@@ -45,7 +49,7 @@
org.hibernate.eg.Foo and foo.barSet
is not foo.BARSET.
- This manual uses lowercase EJBQL keywords. Some users find queries
+ This manual uses lowercase JP-QL keywords. Some users find queries
with uppercase keywords more readable, but we find this convention ugly
when embedded in Java code.
@@ -53,28 +57,28 @@
The from clause
- The simplest possible EJB-QL query is of the form:
+ The simplest possible JP-QL query is of the form:
select c from eg.Cat c
which simply returns all instances of the class
eg.Cat. 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). So we almost always just write:
select c from Cat c
As you may have noticed you can assign aliases to classes, the
- as keywork is optional. An alias allows you to refer
- to Cat in other parts of the query.
+ as keywork is optional. An alias allows you to refer to
+ Cat in other parts of the query.
select cat from Cat as cat
Multiple classes may appear, resulting in a cartesian product or
"cross" join.
- select form, param from Formula as form, Parameter as param
+ select from, param from Formula as form, Parameter as param
It is considered good practice to name query aliases using an
initial lowercase, consistent with Java naming standards for local
@@ -88,7 +92,7 @@
elements of a collection of values, using a
join.
- select cat, mate, kitten from Cat as cat
+ select cat, mate, kitten from Cat as cat
inner join cat.mate as mate
left outer join cat.kittens as kitten
@@ -109,18 +113,18 @@
The inner join, left outer
join constructs may be abbreviated.
- select cat, mate, kitten from Cat as cat
+ select cat, mate, kitten from Cat as cat
join cat.mate as mate
left join cat.kittens as kitten
In addition, a "fetch" join allows associations or collections of
values to be initialized along with their parent objects, using a single
select. This is particularly useful in the case of a collection. It
- effectively overrides the fetching options in the associations and collection
- mapping metadata. See the Performance chapter of the Hibernate reference guide
- for more information.
+ effectively overrides the fetching options in the associations and
+ collection mapping metadata. See the Performance chapter of the Hibernate
+ reference guide for more information.
- select cat from Cat as cat
+ select cat from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
@@ -141,15 +145,12 @@
iterate(). Nor should fetch be used
together with setMaxResults() or
setFirstResult(). It is possible to create a cartesian
- product by join fetching more than one collection in a query (as in the example
- above), be careful the result of this product isn't bigger than you expect.
- Join fetching multiple collection roles also sometimes gives unexpected results for
- bag mappings, so be careful about how you formulate your queries in this case.
-
-
- TODO: The last statement is useless and typical developer thinking, please elaborate.
- The word "sometimes" should never appear in any technical documentation.
-
+ product by join fetching more than one collection in a query (as in the
+ example above), be careful the result of this product isn't bigger than
+ you expect. Join fetching multiple collection roles gives unexpected
+ results for bag mappings as it is impossible for Hibernate to
+ differentiate legit duplicates of a given bag from artificial duplicates
+ created by the multi-table cartesian product.
If you are using property-level lazy fetching (with bytecode
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
left outer join mother.kittens as offspr
- or as an actual typesafe Java object,
+ or as an actual type-safe Java object (often called a view
+ object),
select new Family(mother, mate, offspr)
from DomesticCat as mother
@@ -254,7 +256,8 @@ from Cat cat
You may use arithmetic operators, concatenation, and recognized SQL
- functions in the select clause (dpending on configured dialect, HQL specific feature):
+ functions in the select clause (dpending on configured dialect, HQL
+ specific feature):
select cat.weight + sum(kitten.weight)
from Cat cat
@@ -281,7 +284,7 @@ select count(distinct cat.name), count(cat) from Cat cat
returns instances not only of Cat, but also of
subclasses like DomesticCat. Hibernate queries may name
any Java class or interface in the
- from clause (portable EJB-QL queries should only name
+ from clause (portable JP-QL queries should only name
mapped entities). The query will return instances of all persistent
classes that extend that class or implement the interface. The following
query would return all persistent objects:
@@ -342,7 +345,8 @@ where cat.mate = mate
The special property (lowercase) id may be used
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.
+ mapped identifer property name.). Note that this keyword is specific to
+ HQL.
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
of
+
+ exists, all,
+ any, some (taking
+ subqueries)
+
+
"Simple" case, case ... when ... then ... else ...
end, and "searched" case, case when ... then ...
- else ... end (specific to HQL)
+ else ... end
string concatenation ...||... or
- concat(...,...) (use concat() for portable EJB-QL
+ concat(...,...) (use concat() for portable JP-QL
queries)
@@ -452,9 +462,9 @@ where log.item.class = 'Payment' and log.item.id = payment.id
- Any function or operator defined by EJB-QL 3.0:
- substring(), trim(), lower(), upper(), length(), locate(),
- abs(), sqrt(), bit_length()
+ Any function or operator: substring(), trim(), lower(),
+ upper(), length(), locate(), abs(), sqrt(),
+ bit_length()
@@ -462,6 +472,13 @@ where log.item.class = 'Payment' and log.item.id = payment.id
nullif()
+
+ TYPE ... in ..., 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)
+
+
cast(... as ...), where the second argument
is the name of a Hibernate type, and extract(... from
@@ -490,6 +507,11 @@ where log.item.class = 'Payment' and log.item.id = payment.id
'1970-01-01 10:00:01.0'
+
+ JDBC escape syntax for dates (dependent on your JDBC driver
+ support) (eg. where date = {d '2008-12-31'}
)
+
+
Java public static final constants
eg.Color.TABBY
@@ -548,7 +570,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id
supported when passed the element or index set of a collection
(elements and indices functions) or
the result of a subquery (see below). While subqueries are supported by
- EJB-QL, elements and indices are
+ JP-QL, elements and indices are
specific HQL features.
select mother from Cat as mother, Cat as kit
@@ -567,7 +589,13 @@ where p.name = some elements(list.names)
elements, indices,
minindex, maxindex,
minelement, maxelement - may only be
- used in the where clause in Hibernate3.
+ used in the where clause in Hibernate.
+
+ JP-QL lets you access the key or the value of a map by using the
+ KEY() and VALUE() operations (even
+ access the Entry object using ENTRY())
+
+ SELECT i.name, VALUE(p) FROM Item i JOIN i.photos p WHERE KEY(p) LIKE ‘%egret’
In HQL, elements of indexed collections (arrays, lists, maps) may be
referred to by index (in a where clause only):
@@ -687,7 +715,7 @@ order by count(kitten) asc, sum(kitten.weight) desc
Subqueries
- For databases that support subselects, EJB-QL supports subqueries
+ For databases that support subselects, JP-QL supports subqueries
within queries. A subquery must be surrounded by parentheses (often by an
SQL aggregate function call). Even correlated subqueries (subqueries that
refer to an alias in the outer query) are allowed.
@@ -737,11 +765,11 @@ where not ( cat.name, cat.color ) in (
- EJB-QL examples
+ JP-QL examples
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
- 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
simpler than these!
@@ -848,8 +876,8 @@ order by account.type.sortOrder, account.accountNumber, payment.dueDate
Bulk UPDATE & DELETE Statements
- Hibernate now supports UPDATE and DELETE statements in HQL/EJB-QL. See for details.
+ Hibernate now supports UPDATE and DELETE statements in HQL/JP-QL.
+ See for details.
@@ -888,4 +916,4 @@ from User as usr
group by usr.id, usr.name
having count(msg) = 0
-
\ No newline at end of file
+
diff --git a/entitymanager/src/main/docbook/en/modules/query_native.xml b/entitymanager/src/main/docbook/en/modules/query_native.xml
index 6c4748f112..18d7ab1ce8 100644
--- a/entitymanager/src/main/docbook/en/modules/query_native.xml
+++ b/entitymanager/src/main/docbook/en/modules/query_native.xml
@@ -1,4 +1,4 @@
-
+
-
-
+
Native query
@@ -31,7 +31,7 @@
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
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
refer to the reference guide for more information.)
@@ -42,10 +42,10 @@
description will help the EntityManager to map your
columns onto entity properties. This is done using the
@SqlResultSetMapping annotation. Each
- @SqlResultSetMapping has a name wich is used when
+ @SqlResultSetMapping has a name which is used when
creating a SQL query on EntityManager.
- @SqlResultSetMapping(name="GetNightAndArea", entities={
+ @SqlResultSetMapping(name="GetNightAndArea", entities={
@EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
@FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"),
@@ -65,7 +65,7 @@
You can also define scalar results and even mix entity results and
scalar results
- @SqlResultSetMapping(name="ScalarAndEntities",
+ @SqlResultSetMapping(name="ScalarAndEntities",
entities={
@EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
@FieldResult(name="id", column="nid"),
@@ -103,7 +103,7 @@
third one (not yet supported by Hibernate entity manager), returns pure
scalar results.
- String sqlQuery = "select night.id nid, night.night_duration, night.night_date, area.id aid, "
+ 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 "
+ "and night.night_duration >= ?";
Query q = entityManager.createNativeQuery(sqlQuery, "GetNightAndArea");
@@ -113,7 +113,7 @@ q.getResultList();
This native query returns nights and area based on the
GetNightAndArea result set.
- String sqlQuery = "select * from tbl_spaceship where owner = ?";
+ String sqlQuery = "select * from tbl_spaceship where owner = ?";
Query q = entityManager.createNativeQuery(sqlQuery, SpaceShip.class);
q.setParameter( 1, "Han" );
q.getResultList();
@@ -125,12 +125,12 @@ q.getResultList();
Named queries
- Native named queries share the same calling API than EJB-QL named
+ 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.
- This is very useful for migration from SQL to EJB-QL:
+ This is very useful for migration from SQL to JP-QL:
- Query q = entityManager.createNamedQuery("getSeasonByNativeQuery");
+ Query q = entityManager.createNamedQuery("getSeasonByNativeQuery");
q.setParameter( 1, name );
Season season = (Season) q.getSingleResult();
-
\ No newline at end of file
+
diff --git a/entitymanager/src/main/docbook/en/modules/transactions.xml b/entitymanager/src/main/docbook/en/modules/transactions.xml
index d10c58969c..7ef102c8d4 100644
--- a/entitymanager/src/main/docbook/en/modules/transactions.xml
+++ b/entitymanager/src/main/docbook/en/modules/transactions.xml
@@ -418,7 +418,7 @@
mechanism behind the scenes. The common entity manager and transaction
handling idiom looks like this:
- // Non-managed environment idiom
+ // Non-managed environment idiom
EntityManager em = emf.createEntityManager();
EntityTransaction tx = null;
try {
@@ -501,7 +501,7 @@ finally {
If you use bean-managed transactions (BMT), the code will look
like this:
- // BMT idiom
+ // BMT idiom
@Resource public UserTransaction utx;
@Resource public EntityManagerFactory factory;
@@ -554,13 +554,13 @@ finally {
Our entity manager/transaction management idiom for CMT and EJB3
container-use is reduced to this:
- //CMT idiom through injection
+ //CMT idiom through injection
@PersistenceContext(name="sample") EntityManager em;
Or this if you use Java Context and Dependency Injection
(CDI).
- @Inject EntityManager em;
+ @Inject EntityManager em;
In other words, all you have to do in a managed environment is to
inject the EntityManager, do your data access work,
@@ -834,7 +834,7 @@ finally {
the least efficient in terms of database access. It is the approach most
similar to EJB2 entities:
- // foo is an instance loaded by a previous entity manager
+ // foo is an instance loaded by a previous entity manager
em = factory.createEntityManager();
EntityTransaction t = em.getTransaction();
t.begin();
@@ -895,7 +895,7 @@ em.close();
performance impact. The following examples show the idiom in a
non-managed environment:
- // foo is an instance loaded earlier by the extended entity manager
+ // foo is an instance loaded earlier by the extended entity manager
em.getTransaction.begin(); // new connection to data store is obtained and tx started
foo.setProperty("bar");
em.getTransaction().commit(); // End tx, flush and check version, disconnect
@@ -936,7 +936,7 @@ em.getTransaction().commit(); // End tx, flush and check version, disconnect
EntityManager.merge():
- // foo is an instance loaded by a non-extended entity manager
+ // foo is an instance loaded by a non-extended entity manager
foo.setProperty("bar");
entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();