BT

Handy Improvements in JPA 2.2

| by Kesha Williams Follow 2 Followers on Jan 13, 2018. Estimated reading time: 3 minutes |

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.

 

Rate this Article

Adoption Stage
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Discuss

Login to InfoQ to interact with what matters most to you.


Recover your password...

Follow

Follow your favorite topics and editors

Quick overview of most important highlights in the industry and on the site.

Like

More signal, less noise

Build your own feed by choosing topics you want to read about and editors you want to hear from.

Notifications

Stay up-to-date

Set up your notifications and don't miss out on content that matters to you

BT