Oracle recently released version 2.2 of the Java Persistence API (JPA), which is the standard for persisting Java objects to a relational database.

As a part of the Java EE 8 platform, JPA 2.2 includes support for streaming query results, injecting managed beans into attribute converters, repeating annotations, and working with classes in the Java 8 Date and Time API. Although the changes are few, they are significant because JPA 2.2 is the first version that takes Java 8 as a baseline.

Josh Juneau, in his article (in the Nov / Dec 17 issue of Java Magazine), "What's New in JPA 2.2" remarked:

At last, JPA is brought into alignment with Java SE 8, allowing developers to make use of features such as Date and Time API, streaming query results, and repeatable annotations.



Streaming query results

The getResultStream() method was added to both the Query and TypedQuery interfaces; this improvement returns a stream of results, providing a convenient way to work with data. Prior to JPA 2.2 only lists were returned from a query. The new streaming methods can be used like this:

Stream<Stock> stocks = entityManager

.createNamedQuery(Stock.FIND_HIGH_PERFORMERS, Stock.class)

.getResultStream();

stocks.filter(...)

Streams help queries perform better; however, in some cases, ResultSet pagination may perform better when working with large datasets. There are some persistence providers that take this performance hit into consideration by providing a better implementation of getResultStream() . Developers should consider performance when using streams with large datasets.

Injectable attribute converters

JPA 2.2 introduces the ability to inject managed beans into attribute converters using Contexts and Dependency Injection (CDI)'s @Inject annotation. To utilize this feature, inject CDI resources into any attribute converter, as needed.

@Converter(autoApply = true)

public class TheAttributeConverter implements AttributeConverter<TheObject, String> {

@Inject

private MyUtils utils;



@Override

public TheObject convertToEntityAttribute(String s) {

return utils.toTheObject(s);

}

@Override

public String convertToDatabaseColumn(TheObject obj) {

return utils.toString(obj);

}

}

Repeatable annotations

All annotations for which there exists a container annotation are now repeatable, which allows for multiple instances of the same annotation on a class, method, or attribute. With JPA 2.2, the following annotations are repeatable:

AssociationOverride

AttributeOverride

Convert

JoinColumn

MapKeyJoinColumn

NamedEntityGraph

NamedNativeQuery

NamedQuery

NamedStoredProcedureQuery

PersistenceContext

PersistenceUnit

PrimaryKeyJoinColumn

SecondaryTable

SqlResultSetMapping

This improvement eliminates the need to use container annotations, making code easier to read, and allowing constructions such as:

@Entity

@NamedQuery(name = "Stock.findBySymbol", query = "SELECT s FROM Stocks s WHERE s.symbol = :symbol")

@NamedQuery(name = "Stock.findByDate", query = "SELECT s FROM Stocks s WHERE s.date = :date")

@NamedQuery(name = "Stock.findByPrice", query = "SELECT s FROM Stocks s WHERE s.price = :price")

public class Stock {

...

}

Java 8 date and time support

JPA 2.2 provides basic support for Java 8 date and time types and includes the following mappings for classes in java.time :

LocalDate

LocalTime

LocalDateTime

OffsetTime

OffsetDateTime

Unlike previous versions of JPA, there is no longer a need to write attribute converters to perform mapping from database date and time types to Java 8 date and time types (and vice versa). Because support is built in for the Java Date and Time API, there is no extra work required to use the five supported types and they simply slot in to the existing API:

@Entity

public class Stock implements Serializable {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

@Column(name = "ID", updatable = false, nullable = false)

private Long id;



@Column(name="LAST_BUY_DATE")

private LocalDate lastBuyDate;



@Column(name="LAST_BUY_TIME")

private LocalDateTime lastBuyTime;

}

Since these improvements are a part of the Java EE 8 platform, only compliant application servers provide them out of the box. However, earlier Java EE versions can access them by simply including the applicable JAR files in the project.

More details can be found in the release notes for the Java Persistence 2.2 maintenance release.