X

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 href="http://blogs.oracle.com/arungupta/entry/jax_rs_2_0_and">one
of the first JSRs to be filed as part of href="http://blogs.oracle.com/arungupta/entry/java_ee_7_key_features">Java
EE 7. Several other specifications in Java EE 7 have released
early drafts as well (href="http://jcp.org/aboutJava/communityprocess/edr/jsr344/">JavaServer
Faces 2.0, href="http://jcp.org/aboutJava/communityprocess/edr/jsr339/index.html">JAX-RS
2.0, href="http://jcp.org/aboutJava/communityprocess/edr/jsr346/index.html">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.
    • style="font-weight: bold;">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 href="http://java.net/projects/jpa-spec/lists/jsr338-experts/archive/2011-07/message/12">jsr338-experts
    alias archive and href="http://java.net/projects/jpa-spec/lists/users/archive/2011-07/message/1">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:

  • JPA 2.1
    Specification
  • href="http://java.net/projects/jpa-spec/downloads/download/JPA21Javadocs.zip">Javadocs

  • href="http://wiki.eclipse.org/EclipseLink/Development/JPA_2.1">Implementation
    in EclipseLink


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


Join the discussion

Comments ( 6 )
  • Jason Porter Monday, January 23, 2012

    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.


  • guest Tuesday, January 24, 2012

    and multi tenancy?


  • guest Tuesday, January 24, 2012

    Jason,

    Please follow up on manual flush mode on the alias.

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


  • Eko Kurniawan Khannedy Sunday, February 12, 2012

    nice


  • guest Thursday, November 15, 2012

    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.


  • guestdarren Sunday, April 14, 2013

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


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services