Simple database integration with the JPA persistence.xml file

JPA-based applications can't connect to a database on their own. Rather, they need help in terms of what credentials to use, which schema to seek, which JDBC driver to select and which annotated JavaBeans to manage.

Fulfillment of the connectivity contract that allows the Java application to integrate with a back-end database is the promise the JPA persistence.xml file brings to fruition.

What is the persistence.xml file?

When a developer bootstraps a JPA-based application, the framework searches for the persistence.xml file in a folder named META-INF somewhere on the JVM's classpath. This file contains several properties that the persistence context reads and subsequently uses to decide which JavaBeans to manage at runtime. The persistence.xml properties also inform the JPA framework about how to connect to the back-end database. Once the file knows which entity beans to manage at runtime and obtains a persistent connection to the relational datastore, the application and data layer integration is complete. The persistence.xml file is the component that makes database integration possible in JPA-based applications.

Like all XML, the JPA persistence.xml file starts off with the requisite, bloated assortment of namespace and schemaLocation references. Make sure the version referenced here is compatible with the JPA distribution you link to both at runtime and compile time. Name the file persistence.xml and place it in the META-INF classpath folder. The upper- and lower-case nature of the names are not optional. If the files aren't properly named, it will result in a no persistence.xml file found in project error.

JPA persistence.xml properties
Hibernate specific properties in a JPA persistence.xml file

Database integration with JPA and Hibernate

The JPA persistence.xml file makes possible integration between the database and Java applications.

The hook between Java programs and the XML file is the name of the persistence-unit. In this example, the persistence-unit is named jpa-tutorial.

<persistence-unit name="jpa-tutorial">

When a JPA-based application bootstraps, this name is directly referenced in a tightly coupled manner:

Persistence.createEntityManagerFactory("jpa-tutorial");

If you don't see the relationship, imagine this line of code as a handshake between your Java source code and the JPA framework. When the JPA framework subsequently shakes hands with the underlying relational database, the application and persistence layers integrate.

Managed entities and the persistence.xml file

After the developer names the persistence unit, it's customary to list all the JPA annotated Java classes that are part of the persistence layer. It's also possible to exclude any you'd prefer not to have managed. By default, the JPA framework will manage all JPA annotated classes found in the root of the application, but it won't dig through all the JAR files in the extended classpath for @Entity annotations.

Developers have the option to specify that JPA should only manage classes listed in the persistence.xml file if that's a better fit. It's also possible to reference any external JAR files that might also contain JPA entities.

<jar-file>hibernate-and-jpa-entities.jar</jar-file>
<exclude-unlisted-classes>true</exclude-unlisted-classes>

The persistence.xml must contain all the information required to build a JDBC connection with the back-end database. At a bare minimum, the JPA persistence.xml file must specify values for the following properties:

  • persistence.jdbc.driver
  • persistence.jdbc.url
  • persistence.jdbc.user
  • persistence.jdbc.password

All these properties map back to the basic, required fields to create a standard JDBC connection, which is exactly what the JPA framework is trying to do.

<property name="javax.persistence.jdbc.driver" 
   value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url"
   value="jdbc:mysql://localhost/hibernate_examples"/> 
<property name="javax.persistence.jdbc.user" 
   value="root"/> 
<property name="javax.persistence.jdbc.password" 
   value="password"/>

Sometimes, this minimal set of properties isn't enough for seamless database connections. Some frameworks require developers to add non-standard properties. A good example is the hibernate.dialect property that is required for JBoss's persistence framework to properly query MySQL 8 installations:

<property name="hibernate.dialect" 
          value="org.hibernate.dialect.MySQL8Dialect" />

JNDI datasource configuration

Most enterprise environments typically provide a Java Naming and Directory Interface (JNDI) bound Java Transaction API datasource that already has the relational database connection configured. If a developer deploys to a Tomcat or Jetty server with JNDI configured, they can bypass the basic JDBC settings and simply provide the JNDI name of the datasource:

<jta-data-source>
  java:app/jdbc/HibernateJpaDatasource
</jta-data-source>

Database integration optimizations

The persistence.xml file isn't just about creating a database connection. It also allows a developer to define startup and runtime behaviors. For example, they can set query and lock timeouts to control runtime behavior:

<property name="javax.persistence.query.timeout" value="99"/>
<property name="javax.persistence.lock.timeout" value="99"/>

Perhaps the one persistence.xml property that can have the biggest effect on JPA performance is the cache mode:

<shared-cache-mode>ALL</shared-cache-mode>

The cache mode can take on one of four values:

  • All -- cache all JPA entities;
  • None -- turn of the shared cache;
  • ENABLE_SELECTIVE -- only cache entities with a @Cacheable annotation; or
  • DISABLE_SELECTIVE -- cache all entities that do not specify @Cacheable(false).

Automatic database creation settings

Perhaps the most compelling feature of the persistence.xml file for developers is the fact that it can instruct the JPA to create new database tables as soon as the persistence context is initialized. This technique, also known as top-down database generation, allows developers to model objects in code with the knowledge that it will automatically be supported by the underlying database. Furthermore, the file's ability to re-create database tables and populate them with an SQL script makes it possible for developers to create predictable and repeatable unit tests for the data layer. It's also a great way to validate a new Hibernate and JPA development environment setup.

The two persistence.xml properties that allow the framework to generate databases and load records into tables are:

  • persistence.schema-generation.database.action
  • persistence.sql-load-script-source

Also, the valid options for the database.action property are:

  • create
  • drop-and-create
  • drop
  • none
<property 
  name="javax.persistence.schema-generation.database.action" 
  value="drop-and-create" />
<property name="javax.persistence.sql-load-script-source" 
  value="table-records.sql" />

At its core, the JPA persistence.xml file provides the key properties and parameters needed to allow full integration between JPA frameworks -- like Hibernate -- to both the Java source code that references them and the relational databases to which they connect.

View All Videos