Java and XML based JPA Persistence Unit Configurations

Here in this tutorial I am going to tell you how to configure Persistence Unit for JPA (Java Persistence API). Here I am going to show you both XML and Java based configurations for persistence unit in JPA. This is a pure Java application and I am not using Spring framework for this example.

A persistence unit defines the details that are required when you acquire an entity manager. To package your EclipseLink JPA application, you must configure the persistence unit during the creation of the persistence.xml file. Define each persistence unit in a persistence-unit element in the persistence.xml file.

You need to use the persistence.xml file to package your entities. Once you choose a packaging strategy, place the persistence.xml file in the META-INF directory of the archive of your choice.

Related Posts:

Prerequisites

Java at least 8, Hibernate 6.0.0.Alpha, MySQL Connector 8.0.21, Maven 3.6.3, Gradle 6.7.1

Project Setup

You can create either gradle or maven based project in your favorite tool or IDE.

If you are creating maven based project then you can use the following pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>jpa-persistence-unit-java-xml-config</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.hibernate.orm</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>6.0.0.Alpha6</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.21</version>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement><!-- lock down plugins versions to avoid using Maven 
				defaults (may be moved to parent pom) -->
			<plugins>
				<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
				<plugin>
					<artifactId>maven-clean-plugin</artifactId>
					<version>3.1.0</version>
				</plugin>
				<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
				<plugin>
					<artifactId>maven-resources-plugin</artifactId>
					<version>3.0.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
				</plugin>
				<plugin>
					<artifactId>maven-surefire-plugin</artifactId>
					<version>2.22.1</version>
				</plugin>
				<plugin>
					<artifactId>maven-jar-plugin</artifactId>
					<version>3.0.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-install-plugin</artifactId>
					<version>2.5.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-deploy-plugin</artifactId>
					<version>2.8.2</version>
				</plugin>
				<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
				<plugin>
					<artifactId>maven-site-plugin</artifactId>
					<version>3.7.1</version>
				</plugin>
				<plugin>
					<artifactId>maven-project-info-reports-plugin</artifactId>
					<version>3.0.0</version>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

If you are creating gradle based project then you can use the following build.gradle script:

plugins {
    id 'java-library'
}

sourceCompatibility = 12
targetCompatibility = 12

repositories {
    jcenter()
}

dependencies {
	implementation 'org.hibernate.orm:hibernate-entitymanager:6.0.0.Alpha6'
	
	implementation 'mysql:mysql-connector-java:8.0.21'
}

XML Based Persistence Unit

If you want to configure XML based persistence unit configuration for JPA then you need to create a file called persistence.xml under src/main/resources/META-INF folder.

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
	version="2.2">

	<persistence-unit name="jpaPersistanceUnit"
		transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

		<class>com.roytuts.jpa.persistence.unit.java.xml.config.entity.User</class>

		<properties>
			<property name="javax.persistence.jdbc.driver"
				value="com.mysql.cj.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url"
				value="jdbc:mysql://localhost:3306/roytuts" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password"
				value="root" />
			<property name="dialect"
				value="org.hibernate.dialect.MySQLDialect" />

			<property
				name="hibernate.transaction.flush_before_completion" value="true" />

			<property name="hibernate.show_sql" value="true" />
			<property name="hibernate.format_sql" value="true" />
		</properties>
	</persistence-unit>
</persistence>

Then you need to create EntityManager to query your database. The above XML file gets loaded automatically in your application. You just need to access the persistence unit name you have configured into your XML configuration.

final EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpaPersistanceUnit");

EntityManager em = factory.createEntityManager();

Now you can use the variable em to begin transaction, execute your query, rollback on exception, commit transaction, etc.

Java Based Persistence Unit

Now I will show you how to create Java based persistence unit for your JPA application. There is no short cut to do it. You have to implement the PersistenceUnitInfo interface for Java based configurations.

You need to then override the methods in this interface. I will show you here. Most of the methods are self explanatory.

private static PersistenceUnitInfo persistenceUnitInfo() {
	return new PersistenceUnitInfo() {
		@Override
		public String getPersistenceUnitName() {
			return "jpaPersistenceUnit";
		}

		@Override
		public String getPersistenceProviderClassName() {
			return HibernatePersistenceProvider.class.getName();
		}

		@Override
		public PersistenceUnitTransactionType getTransactionType() {
			return PersistenceUnitTransactionType.RESOURCE_LOCAL;
		}

		@Override
		public DataSource getJtaDataSource() {
			return null;
		}

		@Override
		public DataSource getNonJtaDataSource() {
			return null;
		}

		@Override
		public List<String> getMappingFileNames() {
			return Collections.emptyList();
		}

		@Override
		public List<URL> getJarFileUrls() {
			try {
				return Collections.list(this.getClass().getClassLoader().getResources(""));
			} catch (IOException e) {
				throw new UncheckedIOException(e);
			}
		}

		@Override
		public URL getPersistenceUnitRootUrl() {
			return null;
		}

		@Override
		public List<String> getManagedClassNames() {
			Class<?>[] classes = new Class<?>[] { User.class };

			return Arrays.asList(classes).stream().map(Class::getName).collect(Collectors.toList());
		}

		@Override
		public boolean excludeUnlistedClasses() {
			return false;
		}

		@Override
		public SharedCacheMode getSharedCacheMode() {
			return SharedCacheMode.UNSPECIFIED;
		}

		@Override
		public ValidationMode getValidationMode() {
			return ValidationMode.AUTO;
		}

		@Override
		public Properties getProperties() {
			return properties();
		}

		@Override
		public String getPersistenceXMLSchemaVersion() {
			return "2.2";
		}

		@Override
		public ClassLoader getClassLoader() {
			return Thread.currentThread().getContextClassLoader();
		}

		@Override
		public void addTransformer(ClassTransformer transformer) {

		}

		@Override
		public ClassLoader getNewTempClassLoader() {
			return null;
		}
	};
}

The properties method is defined as follows. You can also use the constants from org.hibernate.cfg.AvailableSettings interface instead putting fully qualified names as keys in the properties.

For example, you can use org.hibernate.cfg.AvailableSettings.JPA_PERSISTENCE_PROVIDER instead of "javax.persistence.provider" as a key for the properties.

private static Properties properties() {
	final Properties properties = new Properties();

	properties.put("javax.persistence.provider", "org.hibernate.jpa.HibernatePersistenceProvider");
	properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");

	properties.put("dialect", "org.hibernate.dialect.MySQLDialect");
	properties.put("javax.persistence.jdbc.driver", "com.mysql.cj.jdbc.Driver");
	properties.put("javax.persistence.jdbc.url", "jdbc:mysql://localhost:3306/roytuts");
	properties.put("javax.persistence.jdbc.user", "root");
	properties.put("javax.persistence.jdbc.password", "root");

	// properties.put("hibernate.cache.use_second_level_cache", "true");
	// properties.put("hibernate.cache.use_query_cache", "true");

	properties.put("hibernate.transaction.flush_before_completion", "true");
	properties.put("hibernate.show_sql", "true");
	properties.put("hibernate.format_sql", "true");

	return properties;
}

Then you can create EntityManager as shown below.

final EntityManagerFactory factory = new HibernatePersistenceProvider().createContainerEntityManagerFactory(persistenceUnitInfo(), properties());

EntityManager em = factory.createEntityManager();

The whole source can be found later in this tutorial from Source Code section.

Testing the Application

I have created just a class with main method to check whether EntityManager is getting created or not.

package com.roytuts.jpa.persistence.unit.java.xml.config;

import javax.persistence.EntityManager;

public class JpaPersistenceUnitApp {

	public static void main(String[] args) {
		EntityManager em = PersistenceUnitConfig.getEntityManager();

		System.out.println("em.isOpen(): " + em.isOpen());

		em.close();
	}

}

Running the above main class will give you the following output:

 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [name: jpaPersistanceUnit]
 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.0.0.Alpha6
 PM org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl <init>
WARN: HHH000059: Defining hibernate.transaction.flush_before_completion=true ignored in HEM
 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: com.mysql.cj.jdbc.Driver
 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:mysql://localhost:3306/roytuts]
 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=root}
 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 20 (min=1)
 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
em.isOpen(): true

That’s all about how to config XML and Java based persistence unit in JPA without using Spring framework.

Source Code

Download

Leave a Comment