JPA

JPA 2.1 – Converters

20th February 2016 Java EE, JPA, Software development No comments

Converting values between object data model and relation data model in JPA 2 is super easy. Here are the steps:

1. Declare converter for value pair thet you want to be converted. Let’s say that we want to convert boolean values to integer, then we declare converter like this:

Converter has to implement javax.persistence.AttributeConverter<ObjectModelType, RelationalModelType>. This interface declared to methods with very clear names – at first sight one can tell what they are responsible for.

Instead of using annotation you can use XML descriptor of course.

2.a Declare Converter class to be applied automatically – just add autoApply attribute set to true to Converter annotation:

2. b If Converter is not applied automatically then annotate entity, mapped superclass or embeddable class attribute with javax.persistence. Convert annotation (or add appropriate XML element to XML descriptor).

converter attribute specifies Converter class to be used for conversion.

If you annotate attribute that is not a basic type or element collection of basic types than you must also add attributeName attribute to annotation to tell JPA to which attribute you want the converter to be applied to.

Convert annotation can also exclude or or overwrite default conversion, e.g. if we have defined some other converter like:

than this converter would not be applied to aforementioned locked field because other converter is specified directly on field.

In order to exclude this attribute from conversion Converter annotation must have disableConversion attribute specified with value true.

Some hints:

According to JPA 2.1 specification point 11.1.10 Convert Annotation some attributes should not be applied to some fields like id, Enumerated and Temporal (annotated) types, relationship attributes or version attributes.

Convert annotation can be applied to entity class that extends mapped superclass to overwrite conversion mapping, see point 11.1.10 Example 11: Override conversion mappings for attributes inherited from a mapped superclass.

When using converter in Java SE environment one needs to specify converter class in persistence.xml, same as with entity classes.

That’s it ! Have a nice day 🙂

JPA 2.1 – generating database for unit and integration tests

24th January 2016 JPA No comments

Generating db for unit tests is pretty easy in JPA 2.1 or rather as easy as it was but a lot more portable an with more management options. We have a few new entries available in persistence.xml (8.2.1.9 properties of JPA 2.1 spec), relevant to db creation are:

  • javax.persistence.schema-generation.create-script-source – this entry points jpa provider to script used when creating db
  • javax.persistence.schema-generation.drop-script-source – this entry points jpa provider to script used when tearing down db
  • javax.persistence.sql-load-script-source – this entry points jpa provider to script that is to load the data
  • javax.persistence.schema-generation.database.action – what action should be done for database – is the JPA provider to create database, drop it or both (drop-and-create) or maybe none?
  • javax.persistence.schema-generation.scripts.action – as above but used for generation of script files
  • javax.persistence.schema-generation.create-source – what source of information should JPA provider use when creating database – scripts, metadata or maybe scripts-then-metadata or metadata-then-script
  • javax.persistence.schema-generation.drop-source – as above but for dropping database
  • javax.persistence.schema-generation.scripts.create-target – target location for create instructions script
  • javax.persistence.schema-generation.scripts.drop-target- target location for drop instructions script

Example configuration:

In the example above H2 database is created in Oracle compatibility mode. Scripts are generated in root folder of project but not used to create or drop database. I used them to make creation of load script easier. Load script is read from src/main/resources 🙂 Hibernate will also read it from root folder, but EclipseLink refuses to do so.

Interesting option is using metadata to create DB and then ddl script to add some specific details or add stored procedures (yes, you could do it e.g. in hibernate using hibernate.cfg.xml but current solution is more portable).

Important detail – notice that all classes are listed in Persistence Unit. Some providers will support class detection when PU is bootstrapped in Java SE environment, some do not. It is safer to list classes. Code that uses unit tests and bootstraps database can be downloaded from GitHub.

If portability is not connected to losing some functionality than why not to use this option ? On the other hand if the price would be to sacrifice some required and well designed, written and maintained functionality that better solution would be to encapsulate the provided dependent part than to use the portable mechanism.

Have en dejlig dag!

JPA 2.1 named entity graphs in Hibernate and EclipseLink

21st January 2016 Java EE, JPA No comments

JPA 2.1 enables us to use named entity graphs that describe what part of entity graph should be loaded. Instead of using one default graph described by FetchType attributes on relation fields and basic fields (in this case code weaving is required) we can now define a few named graphs. Should I mention Fetch Joins used in JPQL and Criteria API ? Well, I don’t find use cases for these equal:

  • With Fetch Joins you have to duplicate query or use tricks like storing core part of query in one field and then concatenate case specific part. On the other hand you can do advanced filtering, grouping and ordering.
  • With Criteria API you can do the same but you can extract common query part to some method
  • Both with Criteria API and JPQL in order to cache results in L2 Cache you must enable query cache

The use cases for named entity graphs are the ones where we do not need advanced filtering or grouping and we do not want to use query cache. Entities fetched with entity graph are cached in L1 cache if EntityManager cache is used. So how can we use named entity graphs?

Let’s say we are given following tables mapped to entities:

entities

On Customer entity we can specify named entity graphs:

In code snippet above there are two named entity graphs:

  • CRT.CUSTOMERS_WITH_PHONES – this one fetched customer data and phones for the customer
  • CRT.CUSTOMER_DATA – this one fetches only basic customer data

Those graphs are simple, this makes it even easier to show some properties. Every entity graphs is a set of:

  • attributeNodes – defined fields/properties that are to be fetched, they can reference subgraphs. Here we use NamedAttributeNode annotation which  value is field/property name that is to be fetched
  • subgraphs – define graphs for related entities, element collections and embedded classes
  • subclassGraphs – defined subgraph for subclasses

@NamedEntityGraphs defines also the  includeAllAttributes attribute that tells jpa provider do load all entity fields/properties, subgraphs still have to be specified.

Now that we have graphs defined We can use this graphs in two ways:

  • as fetch graphs – in this case if an attribute is not specified in named entity graph (including subgraphs) it is treated like it was lazy loaded
  • as load graphs – in this case default fetch type is used to attributes that are not specified in named entity graph (or one of subgraphs)

Let’s test it !

Hibernate JPA provider test:

We specify fetch graph to be used by setting a hint in query instance. As a hint value we specify named entity graph retrieved from EntityManager –  newEntityManager.getEntityGraph(Customer.CUSTOMER_DATA). Orders and phones are not fetched. Note that we use “javax.persistence.fetchgraph” hint – so the fields/properties not specified in graph will be treated as lazy loaded.

Let’s test graph with phones:

Here we using fetch graph but this time named entity graph included phones and they are loaded.

How about load graph ?

In test above named entity graph does not specify phones or orders, but load graph hint is used so default fetch type applies. And both order and phones are not fetched.

How about finder method? Let’s see:

Named entity graphs work in same way. Additionally with query logging enabled we can se that query for customer will be done once.

If we would like to use named entity graphs with O2O relations or basic fields/properties that we will be disappointed:

Both Hibernate and Eclipselink will fetch additional fields in case of One2One mapping and basic properties, and to this according to JPA Spec.

I think I’d rather stick to Fetch Joins and criteria API.

Code with examples will be  are available on GitHub

Cheers !

JPA 2.1 – constructor expressions

21st December 2015 Java EE, JPA No comments

In cases where we fetch lists of data we should fetch as little data as it is reasonable. What is reasonable amount of data ? If we fetch a list with 25 records and display 3 out of 4 entity properties then we fetch whole entity. But if amount of data is controlled by the user (say up to about 100 records per page) or better something like value list holder with in memory cach is implemented, and if there can be several users then we should really design our domain services to return data needed for displaying the view and performing further operations and not much more. An example of bad design would be a list that displays 5 properties from 2 entities that have together over 15 properties. In this case we fetch up to ten properties without a reason. Some of them may be required to e.g. display details view but not all of them.

In JPA we can solve this issue by querying for individual fields and then working with Object arrays or Tuple objects. We can also use Value Objects constructed using Constructor Expressions. This gives us easier refactoring and maintenance, it is much easier to work with Value Object then array. But prior to JPA 2.1 we were limited to JPQL Constructor expressions. Let’s say we have a Customer entity that references Order entity and a few others and we want to display list of customer (represented by customer name) orders with order date and id. In JPA 2.1 we could do:

This does not solve cases where we must use Criteria API or Native Queries. Starting from JPA 2.1 we can use Constructor Expression !

Same query as above written in Criteria API (JPA 2.1):

Here we use CritieriaBuilder.construct method that takes Class to be constructed and constructor parameters.

If we would need to make a Native Query then we must use the new @ConstructorResult annotation:

@ConstructorResult also requires target class and an array of @ColumnResult annotations that point to column names from the query that will be constructor parameter values. Order of @ColumnResult annotations is important and must be the same in Value Object constructor.

Have a nice day 😉

How to avoid repeating cachable DB queries in JPA

30th August 2015 JPA No comments

JPA has two levels of cache:

  • Persistence Context level cache (L1 Cache) – according to JPA specification an instance of Persistence Context can have at most one references to the instance of given entity representing a row in the database.
  • Second level cache (L2 Cache) –  this cache is shared and entries in it live longer. Internal construction of this cache can vary between JPA providers of course – there can be subtypes of this cache like entity cache, relations cache or query cache.

You car read about those in many articles, including this great article by Caren McDonald.

There are two less obvious thing related to use of L1 Cache. One thing is given straight in Caren McDonald’s article:

L1 Cache is related to Persistence Context not the transaction.

A second not so obvious thing is that when you do the following criteria query:

or do a JPA QL Query then the query will be executed against database each time it gets called. This is because you would need to use query cache and L2 cache to avoid those queries.

In order to avoid querying the database when looking for entity with given identifier more than one time in the scope of one Persistence Context you must use EntityManager find:

Shorter, more readable and more effective. Of course we could make the criteria query version shorter, use some utility methods – the point it would still execute the query. Of course in many cases it won’t matter as much, as you would have to query for given id a few times. But when designing a generic utility or some shared repository be aware of this mechanism.