JPQL queries should be run through the Query
interface. The reference to it may be obtained from the current EntityManager
instance by calling createQuery()
method. If the query is supposed to be used to load entities, we recommend calling createQuery()
and passing the result type as parameter. This will create a TypedQuery
instance.
The methods of Query
mainly correspond to the methods of a standard javax.persistence.Query interface. Let us have a look at the differences.
-
setParameter()
– sets a value to a query parameter. If the value is an entity instance, implicitly converts the instance into its identifier. For example:Customer customer = ...; TypedQuery<Order> query = entityManager.createQuery( "select o from sales$Order o where o.customer.id = ?1", Order.class); query.setParameter(1, customer);
Note that the actual entity is passed as parameter while comparison in the query is done using identifier.
A variant of the method with
implicitConversions = false
does not do such conversion. -
setView()
,addView()
– are similar to theEntityManager
methods with the same names – they define a view, used to load data with the current query and do not affect the view of the entireEntityManager
. -
getDelegate()
– returns an instance ofjavax.persistence.Query
, provided by the ORM implementation.
When a request is run through Query
changes in the current persistent context are ignored, i.e. the query just runs in DB. If the results of selection are the
instances already contained in persistent context, then the query result will contain instances from context and not the ones
read from DB. The following test fragment should clarify this:
TypedQuery<User> query; List<User> list; query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); query.setParameter(1, "testUser"); list = query.getResultList(); assertEquals(1, list.size()); User user = list.get(0); user.setName("newName"); query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); query.setParameter(1, "testUser"); list = query.getResultList(); assertEquals(1, list.size()); User user1 = list.get(0); assertTrue(user1 == user);
This behavior is controlled by openjpa.IgnoreChanges=true
, parameter defined in persistence.xml file of the cuba base project. It is possible to change this parameter in your project by including it in the project's own persistence.xml
.
The queries, which change data (update
, delete
) cause flush of the data from the current persistent context to the database prior to execution. In other words, ORM first
synchronizes the states of entities in the persistent context and DB, and only after that runs the modifying query. We recommend
to run such queries in an unchanged persistent context in order to prevent implicit actions by the ORM, which may have negative
impact on performance.