JPA 2.1 – 12 features every developer should know
Take your skills to the next level!
The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.
If you are a regular reader of this blog, you know that I wrote several articles about features and enhancements introduced with JPA 2.1. One thing that was missing, was a general overview about all the changes. So here it is 🙂
The following paragraphs provide a description of the 12 features and enhancements introduced with JPA 2.1.
Features and Enhancements in JPA 2.1
Named Stored Procedure Query
Sometimes it is easier or more efficient to use a stored procedure to perform the operations within the database. Before JPA 2.1 the only way to call a stored procedure was to use a native query. The newly introduced @NamedStoredProcedureQuery can now be used to annotate a query to call the stored procedure.
I described this in more detail in How to call stored procedures in JPA.
Stored Procedure Query
The Stored Procedure Query is an alternative way to implement a stored procedure call without using annotations. For this purpose, the EntityManager was extended by the createStoredProcedureQuery(String procedureName, Class… resultClasses) method.
You can read more about it in How to call stored procedures in JPA – Part 2.
Attribute Converter
Attribute Converter provide a nice and easy way to define a custom mapping between your property on the entity and the database column. The only thing that is needed is a class that implements the AttributeConverter interface and is annotated with @Converter. You can find a more detailed introduction to Attribute Converter in JPA 2.1 – How to implement an Attribute Converter.
One of the most obvious ways to use an Attribute Converter is to implement a custom type mapping to persist a not supported data type like the new Java Date and Time API: How to persist LocalDate and LocalDateTime with JPA.
Or you can use it to change an existing default mapping, as it was done in JPA 2.1 Attribute Converter – The better way to persist enums.
You could also keep the type and change the stored value to implement some business requirements like encryption: How to use a JPA Attribute Converter to encrypt your data.
Constructor Result Mapping
The @ConstructorResult annotation is a handy addition to the already existing @SqlResultSetMapping and can be used to map the result of a query to a constructor call.
You can read more about it in the constructor result mappings part of the result set mapping series.
Programmatic Named Queries
Named Entity Graph
Lazy loading of relations between entities is a common pattern to load only the required information from the database and to improve the performance of the application. While this is a great feature as long as the related entities are not required, it creates additional load when the relations need to be initialized. There are multiple ways to initialize these lazy relations and using Named Entity Graphs is one of the better ones.
The annotations @NamedEntityGraph, @NamedAttributeNode and @NamedSubGraph allow us to define a graph of entities that will be loaded from the database. You can find a more detailed description on how to do this in JPA 2.1 Entity Graph – Part 1: Named entity graphs.
Entity Graph
Entity Graphs are the second option introduced with JPA 2.1 to define a graph of entities that shall be loaded from the database and their usage is similar to Named Entity Graphs. The only difference is that Entity Graphs are defined via a Java API and not via annotations. Therefore the EntityManager was extended by the createEntityGraph(Class rootType) method. This is explained in more detail in JPA 2.1 Entity Graph – Part 2: Define lazy/eager loading at runtime.
JPQL Enhancements
There were several enhancements to the JPQL which can come in handy. You can now use the keyword ON to define additional join parameters, call database functions by using FUNCTION and downcast entities with TREAT.
Criteria API Bulk Operations
Up to JPA 2.1 the Criteria API did not provide any support for update or delete operations. The only options available were to perform the update on an entity or to write a native query to update multiple records at once. As described in Criteria Update/Delete – The easy way to implement bulk operations with JPA2.1, the Criteria API was extended with CriteriaUpdate and CriteriaDelete to also support bulk write operations.
Unsynchronized Persistence Context
Using a synchronized persistence context to propagate every change to the database is the default approach in JPA. If you need more control about the database propagation, you can now use the unsynchronized persistence context. Therefore you need to provide the synchronization mode to the injection with @PersistenceContext(synchronization=SynchronizationType.UNSYNCHRONIZED). You then need to call EntityManager.joinTransaction() manually to synchronize the changes.
Generating DB Schema
Up to JPA 2.1 you needed to use vendor specific configuration parameter to define the database setup in the persistence.xml file. Starting from version 2.1 there is also a standard way to do this. Therefore the specification defines the following long list of parameters:
- javax.persistence.schema-generation.database.action
- javax.persistence.schema-generation.scripts.action
- javax.persistence.schema-generation.create-source
- javax.persistence.schema-generation.drop-source
- javax.persistence.schema-generation.create-database-schemas
- javax.persistence.schema-generation.scripts.create-target
- javax.persistence.schema-generation.scripts.drop-target
- javax.persistence.database-product-name
- javax.persistence.database-major-version
- javax.persistence.database-minor-version
- javax.persistence.schema-generation.create-script-source
- javax.persistence.schema-generation.drop-script-source
- javax.persistence.schema-generation.connection
- javax.persistence.sql-load-script-source
You can get a more detailed description of the different parameters and some examples how to use them to setup your database in Standardized schema generation and data loading with JPA 2.1.
CDI-Support in Entity Listener
The integration with CDI was improved with JPA 2.1. You can now use CDI to inject beans into EntityListeners and to implement the @PreDestroy and @PostConstruct methods.
What do you mean with “compatible with Java 8”?
EclipseLink and Hibernate work fine with Java 8. But the new types like LocalDate are not supported by JPA because Java 8 was released after JPA 2.1. I am not aware of any JPA implementation that supports these types at the moment.
FWIW, Hibernate does support Java 8 Date/Time types as of 5.0 – http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e451
Could we imagine a support for the Java8 stream api to complement Collection? Also we can dream of calling a filter, distinct, grouBy method on those stream that will be translated in Sql statements by HIB on terminal operation 🙂
That would be an interesting addition. Support for streams is planned for JPA 2.2 but I don’t know any details. Lukas Jungmann will be the spec lead for it and talked about the planned features in his JavaOne talk: https://www.youtube.com/watch?v=1OKEpg5zpsU#t=4h08m25s
EclipseLinks works fine with Java 8, though it did not support lambda in entities and stream on collections before 2.6.0.
I anyone aware of a lightweight JPA 2.1 implementation that is also compatible with Java 8? I tried OpenJPA, but it doesn't appear to support Java 8.