Results for tag "jpa"

JPA Database Schema Generation

posted by Roberto Cortez on

For some time now, most of the main implementations of JPA, like Hibernate, EclipseLink, OpenJPA or DataNucleus, offered ways to generate database schema objects. These include generation of tables, primary keys, foreign keys, indexes and other objects. Unfortunately, these are not standard between the implementations, when dealing with multiple environments. Only in the latest JPA 2.1 specification, the Schema Generation standardization was introduced.

From now on, if you are using Java EE 7, you don’t have to worry about the differences between the providers. Just use the new standard properties and you are done. Of course, you might be thinking that these are not needed at all, since database schemas for environments should not be managed like this. Still, these are very useful for development or testing purposes.

Schema Generation

Properties
If you wish to use the new standards for Schema Generation, just add any of the following properties to your properties section of the persistence.xml:

PropertyValues
javax.persistence.schema-generation.database.action

Specifies the action to be taken regarding to the database schema. Possible values are self-explanatory. If this property is not specific no actions are performed in the database.
none, create, drop-and-create, drop
javax.persistence.schema-generation.create-source

Specifies how the database schema should be created. It can be by just using the annotation metadata specified in the application entities, by executing a SQL script or a combination of both. You can also define the order. This property does not need to be specified for schema generation to occur. The default value is metadata. You need to be careful if you use a combination of create actions. The resulting actions may generate unexpected behaviour in the database schema and lead to failure.
metadata, script, metadata-than-script, script-then-metadata
javax.persistence.schema-generation.drop-source

Same as javax.persistence.schema-generation.create-source, but for drop actions.
metadata, script, metadata-than-script, script-then-metadata
javax.persistence.schema-generation.create-script-source, javax.persistence.schema-generation.drop-script-source

Specifies the target location to a SQL script file to execute on create or drop of the database schema.
String for the file URL to execute
javax.persistence.sql-load-script-source

Specifies the target location to a SQL file to load data into the database.
String for the file URL to execute

Additionally, it’s also possible to generate SQL scripts with the Schema Generation actions:

PropertyValues
javax.persistence.schema-generation.scripts.action

Specifies which SQL scripts should be generated. Scripts are only generated if the corresponding generation location targets are specified.
none, create, drop-and-create, drop
javax.persistence.schema-generation.scripts.create-target, javax.persistence.schema-generation.scripts.drop-target

Specifies the target location to generate the SQL script file to create or drop of the database schema.
String for the file URL to execute

Samples

The following sample, drops and creates the database schema objects needed by the JPA application. Relies on the annotations metadata of the entities and also executes an arbitrary SQL file named load.sql.

Another sample that generates the database schema objects to be created and dropped in the target locations:

Both samples can also be combined for dropping and creating the database objects and generating the corresponding scripts that perform these operations. You can find these and other samples in the Java EE Samples project hosted on Github.

Limitations

As I mentioned before, I recommend that you use these properties for development or testing purposes only. A wrong setting, might easily destroy or mess with your production database.

There are no actions to update or just validate the schema. I couldn’t find the reason why they didn’t make it into the specification, but here is an issue with the improvement suggestion.

The database schema actions are only performed on the application deployment in a Java EE environment. For development, you might want to perform the actions on the server restart.

Support

Both Hibernate and EclipseLink, which are bundled with Wildfly and Glassfish support these properties.

OpenJPA, currently does not support these properties, but I’ve been working in the OpenJPA support for standard Schema Generation. If you’re curious or want to follow the progress, check my Github repo, here. This was actually my main motivation to write this post, since I’m a bit involved in the implementation of the feature.

I hope you enjoyed the post 🙂

JPA Entity Graphs

posted by Roberto Cortez on

One of the latest features in JPA 2.1 is the ability to specify fetch plans using Entity Graphs. This is useful since it allows you to customize the data that is retrieved with a query or find operation. When working with mid to large size applications is common to display data from the same entity in different and many ways. In other cases, you just want to select a smallest set of information to optimize the performance of your application.

You don’t have many mechanisms to control what is loaded or not in a JPA Entity. You could use EAGER / LAZY fetching, but these definitions are pretty much static. You were unable to change their behaviour when retrieving data, meaning that you were stuck with what was defined in the entity. Changing these in mid development is a nightmare, since it can cause queries to behave unexpectedly. Another way to control loading is to write specific JPQL queries. You usually end up with very similar queries and the following methods: findEntityWithX, findEntityWithY, findEntityWithXandY, and so on.

Before JPA 2.1, the implementations already supported a non standard way to load data similar to Entity Graphs. You have Hibernate Fetch Profiles, OpenJPA Fetch Groups and EclipseLink Fetch Groups. It was logical to have this kind of behaviour in the specification. It allows you a much finer and detail control on what you need to load using a standard API.

Example

Consider the following Entity Graph:

Movie Entity Graph

(Probably the relationships should be N to N, but lets keep it simple).

And the Movie Entity has the following definition:

Looking closer to the entity, we can see that we have three 1 to N relationships and movieDirectors is set to be Eagerly loaded. The other relationships are set to the default Lazy loading strategy. If we want to change this behaviour, we can define different loading models by using the annotation @NamedEntityGraph. Just set a name to identify it and then use the @NamedAttributeNode to specify which attributes of the root entity that you want to load. For relationships you need to set a name to the subgraph and then use @NamedSubgraph. In detail:

Annotations

This defines an Entity Graph with name movieWithActors and specifies that the relationship movieActors should be loaded.

This defines an Entity Graph with name movieWithActorsAndAwards and specifies that the relationship movieActors should be loaded. Additionally, it also specifies that the relationship movieActors should load the movieActorAwards.

Note that we don’t specify the id attribute in the Entity Graph. This is because primary keys are always fetched regardless of what’s being specified. This is also true for version attributes.

Hints

To use the Entity Graphs defined in a query, you need to set them as an hint. You can use two hint properties and these also influences the way the data is loaded.

You can use javax.persistence.fetchgraph and this hint will treat all the specified attributes in the Entity Graph as FetchType.EAGER. Attributes that are not specified are treated as FetchType.LAZY.

The other property hint is javax.persistence.loadgraph. This will treat all the specified attributes in the Entity Graph as FetchType.EAGER. Attributes that are not specified are treated to their specified or default FetchType.

For more information, please refer to the sections 3.7.4.1 – Fetch Graph Semantics and 3.7.4.2 – Load Graph Semantics of the JPA 2.1 specification.

To simplify, and based on our example when applying the Entity Graph movieWithActors:

Default / Specifiedjavax.persistence.fetchgraphjavax.persistence.loadgraph
movieActorsLAZYEAGEREAGER
movieDirectorsEAGERLAZYEAGER
movieAwardsLAZYLAZYLAZY

In theory, this should be how the different relationships are fetched. In practice, it may not work this way, because the JPA 2.1 specification also states that the JPA provider can always fetch extra state beyond the one specified in the Entity Graph. This is because the provider can optimize which data to fetch and end up loading much more stuff. You need to check your provider behaviour. For instance Hibernate always fetch everything that is specified as EAGER even when using the javax.persistence.fetchgraph hint. Check the issue here.

Query

Performing the query is easy. You do it as you would normally do, but just call setHint on the Query object:

To get the Entity Graph you want to use on your query, you need to call the getEntityGraph method on the EntityManager and pass the name. Then use the reference in the hint. Hint must be either javax.persistence.fetchgraph or javax.persistence.loadgraph.

Programmatic

Annotations may become verbose, especially if you have big graphs or many Entity Graphs. Instead of using annotations, you can programmatically define Entity Graphs. Let’s see how:

Start by adding a static meta model Entity Class:

This is not really needed, you can reference the attributes by their string names, but this will give you type safety.

This Entity Graph specifies that all relationships of the Entity must be loaded. You can now adjust to your own use cases.

Resources

You can find this sample code in the Java EE samples at Github. Check it here.

Extra Note: currently there is a bug in EclipseLink / Glassfish that prevents javax.persistence.loadgraph hint from working properly. Check the issue here.

Conclusion

Entity Graphs filled a gap missing in the JPA specification. They are an extra mechanism that helps you to query for what you really need. They also help you to improve the performance of your application. But be smart when using them. There might be a better way.

How to use JPA

posted by Roberto Cortez on

Today, my third article How to use JPA correctly to avoid complaints of a slow application was published on RebelLabs. In the last few years I have worked a lot with JPA, so it was a perfect opportunity to write down some of the things I have learned and hopefully help other developers.

Database Slow

A special thanks to RebelLabs for letting me publish my work there and of course to Oliver White for all the support on writing and reviewing the article. You rock!