BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Handy Improvements in JPA 2.2

Handy Improvements in JPA 2.2

Leia em Português

This item in japanese

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
Style

BT