JPA 2.1 Early Draft Explained - Java EE 7 making progress

Java Persistence API 2.1 Early Draft has been available for about a month now. JPA2 was one of the first JSRs to be filed as part of Java EE 7. Several other specifications in Java EE 7 have released early drafts as well (JavaServer Faces 2.0, JAX-RS 2.0, CDI 1.1, more coming as well) and I'll cover them in later blogs.

Here are the main highlights of JPA 2.1:
  • Support for Stored Procedures: Added support for the invocation of predefined database functions and user-defined database functions to the Java Persistence query language.

    There are different variants of EntityManager.createXXXStoredProcedureQuery methods that return a StoredProcedureQuery for executing a stored procedure.  Just liked @NamedQuery, there is @NamedStoredProcedureQuery that specifies and names a stored procedure, its parameters, and its result type. This annotation can be specified on an entity or mapped superclass. The name specified in the annotation is then used in EntityManager.createNamedStoredProcedureQuery. The IN, OUT, and INOUT parameters can be set and used to retrieve values passed back from the procedure. For example:

    @Entity
    @NamedStoredProcedureQuery(name="topGiftsStoredProcedure", procedureName="Top10Gifts")
    public class Product {
     . . .
    }


    // In your client

    StoredProcedreQuery query = EntityManager.createNamedStoredProcedureQuery("topGiftsStoredProcedure");
    query.registerStoredProcedureParameter(1, String.class, ParameterMode.INOUT);
    query.setParameter(1, "top10");
    query.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);
    query.setParameter(2, 100);
    // there are other setParameter methods for defining the temporal type of a parameter
    . . .
    query.execute();
    String response = query.getOutputParameterValue(1);


    The section 3.8.6 provide more details.
  • Bul update/delete using Criteria: Added CriteriaUpdate, CriteriaDelete, CommonAbstractQuery interfaces, refactored AbstractQuery interface.

    Here is a sample for CriteriaUpdate from section 6.5.15:

    CriteriaUpdate<Customer> q = cb.createCriteriaUpdate(Customer.class);
    Root<Customer> c = q.from(Customer.class);
    q.set(c.get(Customer_.status), "outstanding")
     .where(cb.lt(c.get(Customer_.balance), 10000));

    with the equivalent JPQL of:

    UPDATE Customer c
    SET c.status = 'outstanding'
    WHERE c.balance < 10000

    This query can then be executed as:

    @PersistenceContext EntityManager em;
    Query query = em.createQuery(q);
    query.executeUpdate();

    Here is a sample for CriteriaDelete from section 6.5.15:

    CriteriaDelete<Customer> q = cb.createCriteriaDelete(Customer.class);
    Root<Customer> c = q.from(Customer.class);
    q.where(cb.equal(c.get(Customer_.status), "inactive"),
            cb.isEmpty(c.get(Customer_.orders)));

    with the equivalent JPQL of:

    DELETE FROM Customer c
    WHERE c.status = 'inactive'
    AND c.orders IS EMPTY


    This query can then be executed in similar way as earlier:

    @PersistenceContext EntityManager em;
    Query query = em.createQuery(q);
    query.executeUpdate();

  • New reserved keywords: Added the following to Java Persistence query language reserved identifiers: FUNCTION, ON, TREAT.
    • Pre-defined and user-defined functions using FUNCTION: JPQL provide several in-built functions which may be used in the SELECT, WHERE or HAVING clause of a query such as CONCAT, SUBSTRING, TRIM, LENGTH, ABS, SQRT, and CURRENT_DATE. The section 4.6.17.3 define invocation of predefined and user-defined database functions using the FUNCTION operator. The FUNCTION is used to invoke predefined database functions or user-defined database functions. An example from the section is:

      SELECT c
      FROM Customer c
      WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)

    • Downcasting using TREAT: TREAT is supported for downcasting within path expressions in the FROM and WHERE clauses. Use of the TREAT operator allows access to subclass-specific state. An example from section 4.4.9 is:

      SELECT b.name, b.ISBN
      FROM Order o JOIN TREAT(o.product AS Book) b


      In this example, the join is performed between Order and Product but name and ISBN are attributes of the Book class which is a subclass of the Product class. Another example is:

      SELECT e FROM Employee e
      WHERE TREAT(e AS Exempt).vacationDays > 10
      OR TREAT(e AS Contractor).hours > 100


      Here again vacationDays are attributes for Exempt employees only and hours only for Contractor.

    • Join condition using ON: The ON clause in SQL is used to specify the relationship between the tables. It is different from the WHERE clause which specifies the criteria for the rows to be picked. An example from the section 4.4.5.2 shows the JPQL as:

      SELECT s.name, COUNT(p)
      FROM Suppliers s LEFT JOIN s.products p
      ON p.status = 'inStock'
      GROUP BY s.name


      The mapped SQL for this will be:

      SELECT s.name, COUNT(p.id)
      FROM Suppliers s LEFT JOIN Products p
      ON s.id = p.supplierId AND p.status = 'inStock'
      GROUP BY s.name


      The s.id = p.supplierId condition is generated becase of the LEFT JOIN. The additional JOIN condition of p.status = 'inStock' is also added to the generated SQL because of the ON clause in the JPQL. The result of this query will include all suppliers (with possibly NULL values). This is different from the query below:

      SELECT s.name, COUNT(p)
      FROM Suppliers s LEFT JOIN s.products p
      WHERE p.status = 'inStock'
      GROUP BY s.name


      The result of this query will not include suppliers that have no products in stock.

      Additional methods are also added to Fetch, Join, CollectionJoin, SetJoin, ListJoin, and MapJoin interfaces to support the ON clause.
  • Entity listeners using CDI: Entity Listeners allow to handle cross-cutting lifecycle events in a non-persistent listener class. In JPA 2.1, entity listeners will support dependency injection through CDI. The usual lifecycle callback methods of @PrePersist, @PostPersist, @PreUpdate, and @PreRemove can be used for entities. The entity listeners can also be annotated with @PostConstruct and @PreDestroy for their own lifecycle. The section 3.5.1 provides more details on this.

    Read more details on jsr338-experts alias archive and users@jpa-spec.
  • Synchronization of persistence contexts: In JPA 2, the persistence context is synchronized with the underlying resource manager. Any updates made to the persistence context are propagated to the resource manager. JPA 2.1 introduces the concept of unsynchronized persistence contenxt. Here is how you can create a container-managed unsynchronized persistence context:

    @PersistenceContext(synchronization=SynchronizationType.UNSYNCHRONIZED) EntityManager em;

    The section 7.6.1 provide more details.
  • Several clarifications in text and javadocs

The Appendix in the specification provide a comprehensive list of changes in this version of the specification. And there are change bars through out as well allowing you to see what has changed since JPA 2.

Here are some final set of references for you:

And of course, it'll all be delivered as part of GlassFish 4.0!


Comments:

I remember starting a conversation on the list about a manual flush mode, it seemed like people were agreeable to the final proposed solution. Whatever happened there? I know it's been an oft requested feature.

Posted by Jason Porter on January 23, 2012 at 08:13 AM PST #

and multi tenancy?

Posted by guest on January 24, 2012 at 07:56 AM PST #

Jason,

Please follow up on manual flush mode on the alias.

Multi-tenancy is a TBD and will be added to future drafts.

Posted by guest on January 24, 2012 at 09:04 AM PST #

nice

Posted by Eko Kurniawan Khannedy on February 12, 2012 at 12:04 AM PST #

There are some unresolved problems with JPA that are being ignored. For instance, we can't create two collections for the same class type and differentiate the load of each. Something like that:

@OneToMany @Where(condition="flag = 1")
Collection< SomeClass > a;

@OneToMany @Where(condition="flag = 0")
Collection< SomeClass > b;

Currently there is no such a way of doing this simple thing with JPA.

Posted by guest on November 15, 2012 at 10:43 AM PST #

Will disconnected criteria be in this release? Hibernate had them before.

Posted by guestdarren on April 14, 2013 at 04:52 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today