Top Banner
Java Persistence API: Entity Manager Exercise An Introduction to JPA and JPA/Maven Modules Revision: v2018-10-04 Built on: 2019-08-22 07:09 EST Copyright © 2019 jim stafford ([email protected]) This document contains an introductory exercise for building a Maven-based project for modules that make use of a database and JPA. It will provide step-by-step instructions and explanations of what is being added and why. Many of these steps will become boilerplate for what we need to do for most JPA Maven modules. You go through this in detail here to provide you with exposure of what is required and why certain things are in place in the examples. It is also another chance to gain experience building a Maven project from scratch before we start leveraging templates and parent projects to hide much of the details from us.
62

Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Aug 17, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Java Persistence API:

Entity Manager Exercise

An Introduction to JPA and JPA/Maven Modules

Revision: v2018-10-04Built on: 2019-08-22 07:09 EST

Copyright © 2019 jim stafford ([email protected])

This document contains an introductory exercise for building a Maven-based project for modules

that make use of a database and JPA. It will provide step-by-step instructions and explanations of

what is being added and why. Many of these steps will become boilerplate for what we need to do

for most JPA Maven modules. You go through this in detail here to provide you with exposure of

what is required and why certain things are in place in the examples. It is also another chance to

gain experience building a Maven project from scratch before we start leveraging templates and

parent projects to hide much of the details from us.

Page 2: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA
Page 3: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

iii

Purpose ............................................................................................................................ v

1. Goals .................................................................................................................... v

2. Objectives ............................................................................................................. v

1. Setup and Start Database ............................................................................................ 1

1.1. Summary ............................................................................................................ 2

2. Create Core Project POM ............................................................................................ 3

2.1. Summary ............................................................................................................ 9

3. Setup Database Schema ............................................................................................ 11

3.1. Summary .......................................................................................................... 15

4. Add SQL Tuning ........................................................................................................ 17

4.1. Summary .......................................................................................................... 18

5. JPA Persistence Unit Setup ...................................................................................... 19

5.1. Summary .......................................................................................................... 23

6. Setup JPA TestCase .................................................................................................. 25

6.1. Summary .......................................................................................................... 30

7. Ready Project for Import into Eclipse ....................................................................... 33

7.1. Summary .......................................................................................................... 34

8. Test EntityManager Methods ..................................................................................... 35

8.1. Summary .......................................................................................................... 40

9. Automatically Generate Database Schema ................................................................ 41

9.1. Summary .......................................................................................................... 44

10. Create JPA Parent POM ........................................................................................... 45

10.1. Summary ........................................................................................................ 56

Page 4: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

iv

Page 5: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

v

Purpose

1. Goals• Provide one more chance to build a Maven module using step-by-step instructions

• Provide step-by-step instructions for setting up a Maven module for JPA

• Provide an introduction to JPA EntityManager CRUD methods

2. Objectives

At the completion of this topic, the student shall be able to:

• Maven/General project setup

• Setup a database for use with module development

• Create a Maven project for use with a JPA module

• Manage module-specific schema within the database

• Add custom SQL tuning properties to their module schema definition

• Import a Maven/JPA project into IDE

• Automatically generate database schema for project

• Refector single Maven/JPA module into a re-suable parent and individual child modules

• JPA

• Setup a JPA Persistence Unit

• Setup a JPA Unit test

• Implement tests of JPA EntityManager methods

Page 6: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

vi

Page 7: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 1.

1

Setup and Start DatabaseThis chapter will cover setup required to start the development database in server-mode. The

database has at least three (3) modes.

• In-memory mode

• File-based mode

• Server-based mode

The in-memory option manages all tables within the memory footprint of the JVM. This is very fast

and requires no server-process setup -- which makes it a good option for automated unit tests.

However, since the DB instance is created and destroyed with each JVM execution it makes a bad

choice for modules relying on multiple tools to pre-populate the database prior to executing tests.

The file-based option stores all information in the filesystem. It is useful for multi-JVM (sequential)

setup and post-mortem analysis. However only a single client may access the files at one time.

I have seen this used effectively when simulating external databases -- where an external setup

script populates the database and the JVM running the unit tests just queries the information as

they would do in production. We will use this as an option to server-based mode since we are

using separate plugins to initialize the database. We also want to treat our database schema as a

first-class artifact for our application -- and not rely on test capabilities to instantiate the database

for each test.

The server-based option requires a separate process activated but allows concurrent connections

from database user interface while the JVM is under test. This chapter will focus on the setup

required to run the database in server mode.

1. Prepare your environment to run the database in server mode for this exercise by following the

instructions defined in Development Environment Setup.

2. Start the database and web server server in a directory where you wish to create database files.

Your h2.jar file source be located in M2_REPO/com/h2database/h2/*/h2*.jar to name at least

one location. Another location is JBOSS_HOME/modules/com/h2database/h2/main/h2*.jar

cd /tmp

java -jar h2.jar

This should result in a database server process and access to a web-based database UI

through the following local URL: http://localhost:8082/login.jsp

3. Connect to the database server from the web-based UI.

Driver Class: org.h2.Driver

JDBC URL: jdbc:h2:tcp://localhost:9092/./h2db/ejava</jdbc.url>

User Name: sa

Password:

Look in the directory where you started the server. After connecting with a relative URL using

the UI, there should be a new "h2db" directory with one or more files called "ejava*". You want

Page 8: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 1. Setup and Start Da...

2

to make sure you use the same URL in the UI and application so you are seeing the same

instance of the database.

If you use file-based mode, the connection information would look like the following where "./

h2db/ejava" must point to the exact same path your JVM under test uses. This can be a relative

or fully-qualified path.

Driver Class: org.h2.Driver

JDBC URL: jdbc:h2:./target/h2db/ejava

User Name: sa

Password:

1.1. Summary

In this chapter you...

• located a copy of the Java archive required to run the server

• located a scratch area to run the server

• started the server

• launched the web-based UI

• connected to the server using the web-based UI

This is the only database mode that requires administrative setup. You cannot connect to the

database running in-memory but you can connect to the database using file-mode once all other

JVMs have released their exclusive lock on the database storage files.

Page 9: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 2.

3

Create Core Project POMThis chapter will put in place a couple of core constructs that will allow Maven and the IDE

recognize the elements of your source tree.

1. Create a root directory for your project and populate with a pom.xml file

<?xml version="1.0"?>

<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/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>myorg.jpa</groupId>

<artifactId>entityMgrEx</artifactId>

<version>1.0-SNAPSHOT</version>

<name>Entity Manager Exercise</name>

</project>

2. Define a remote repository to use to download hibernate artifacts

<!-- needed to resolve some hibernate dependencies -->

<repositories>

<repository>

<id>jboss-nexus</id>

<name>JBoss Nexus Repository</name>

<url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>

</repository>

</repositories>

3. Add property definitions for versions of dependencies and plugins we will be using.

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<java.source.version>1.8</java.source.version>

<java.target.version>1.8</java.target.version>

<jboss.host>localhost</jboss.host>

<db.host>${jboss.host}</db.host>

<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>

<maven-jar-plugin.version>3.1.0</maven-jar-plugin.version>

<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>

<sql-maven-plugin.version>1.5</sql-maven-plugin.version>

<h2db.version>1.4.197</h2db.version>

<javax.persistence-api.version>2.2</javax.persistence-api.version>

<hibernate-entitymanager.version>5.3.1.Final</hibernate-entitymanager.version>

<junit.version>4.12</junit.version>

Page 10: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 2. Create Core Projec...

4

<log4j.version>1.2.17</log4j.version>

<slf4j.version>1.7.25</slf4j.version>

<ejava.version>5.0.0-SNAPSHOT</ejava.version>

</properties>

4. Add a dependencyManagement section to define and configure the dependencies we will be

using to work with JPA. These are passive definitions -- meaning they don't actually add any

dependencies to your project. They just define the version and possible exclusions for artifacts

so all child/leaf projects stay consistent.

<dependencyManagement>

<dependencies>

<dependency>

<groupId>javax.persistence</groupId>

<artifactId>javax.persistence-api</artifactId>

<version>${javax.persistence-api.version}</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<version>${hibernate-entitymanager.version}</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${slf4j.version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>${slf4j.version}</version>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>${log4j.version}</version>

</dependency>

</dependencies>

</dependencyManagement>

Note

Knowing this exercise will always be a single module -- we could do this

simpler. However, it is assumed that you will soon take the information you

learn here to a real enterprise project and that will have many modules and

could benefit from reusing a standard parent configuration. All definitions will be

housed in a single module during the conduct of this exercise but the properties,

Page 11: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

5

dependencyManagement, and pluginManagement sections we will build below

can be lifted and moved to a parent pom in a multi-module project.

5. Add pluginManagement definitions for certain plugins we will use in this module. Like above --

these are passive definitions that define the configuration for certain plugins when the child/leaf

projects chose to use them. Lets start with a simple example and add a few more complex ones

later. In this example, we are making sure all uses of the jar plugin are of a specific version.

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-jar-plugin</artifactId>

<version>${maven-jar-plugin.version}</version>

</plugin>

</plugins>

</pluginManagement>

</build>

6. Add the src/main dependencies. This represents what your code depends upon at compile time

and runtime.

• scope=compile is used when your src/main code depends on the artifact to compile and you

wish the design of transitive dependency to automatically bring this dependency with the

module.

• scope=provided is used when your src/main code depends on the artifact to compile but you

do not wish this automatically be brought along when used with downstream clients. Normally

this type of artifact is an API and the downstream client will be providing their own version

of the API packaged with their provider.

<dependencies>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.persistence</groupId>

<artifactId>javax.persistence-api</artifactId>

<scope>provided</scope>

</dependency>

...

</dependencies>

Page 12: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 2. Create Core Projec...

6

Note

Notice how the definitions above are lacking a version element. The dependency

declaration actively brings the dependency into the project and inherits the

definition specified by the dependencyManagement section above.

7. Add the src/test standard dependencies.

• scope=test is used for anything that your src/test code depends upon (but not your src/main)

or what your unit tests need at runtime to operate the test. For example, a module may

declare a scope=test dependency on h2 database (later) to do some local unit testing and

then be ultimately deployed to a postgres server in a downstream client. In this case we are

picking JUnit4 as the testing framework, log4j as the logging implementation for commons-

logging, and hibernate as the JPA implementation for the jpa-api. We are also adding an

extra dependency to allow hibernate slf4j logging to be integrated with log4j.

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<scope>test</scope>

</dependency>

8. Add a testResources definition to the build section to get src/test/resource files filtered when

copied into the target tree. We do this so we have a chance to replace the variables in the

persistence.xml and hibernate.properties file.

<build>

<!-- filtering will replace URLs, credentials, etc in the

files copied to the target directory and used during testing.

-->

<testResources>

<testResource>

<directory>src/test/resources</directory>

<filtering>true</filtering>

</testResource>

Page 13: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

7

</testResources>

<pluginManagement>

...

</build>

9. Add a compiler specification to control the source and target java versions. In this case we are

picking up the specific value from property variables set above and can be overridden in the

developer's settings.xml or on the command line using system properties.

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>${maven-compiler-plugin.version}</version>

<configuration>

<source>${java.source.version}</source>

<target>${java.target.version}</target>

</configuration>

</plugin>

...

</plugins>

</pluginManagement>

</build>

10.Add a definition for the maven-surefire-plugin so we can set properties needed for testing.

<build>

<pluginManagement>

<plugins>

...

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

<version>${maven-surefire-plugin.version}</version>

<configuration>

<argLine>${surefire.argLine}</argLine>

</configuration>

</plugin>

</plugins>

</pluginManagement>

</build>

Note

At this point, we are just allowing the argLine defined elsewhere to be optionally

specified (for debugging). We do not yet have a need for system properties, but

if we did the example shows how -Dname=value would be specified within the

Page 14: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 2. Create Core Projec...

8

plugin configuration. The plugin (not pluginManagement) definition in the child

pom will include any necessary system properties to be passed to the unit test.

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

<configuration>

<systemPropertyVariables>

<name1>value1</name1>

<name2>value2</name2>

</systemPropertyVariables>

</configuration>

</plugin>

11.Add a set of profiles that define H2 and Hibernate as our database and persistence provider. In

the example below we are adding two database definitions (that happen to both be the same

vendor). One requires the server to be running and the other uses an embedded server and

a local filesystem. The embedded version can be easier to test with. The server version can

be easier to debug. Activate which one you want with either your settings.xml#activeProfile

settings or using a -Pprofile-name argument on the command line. If you already have a

settings.xml#activeProfile setting, you can turn it off using -P\!deactivated-profile-name ((bash)

or -P!deactivated-profile-name (dos)) and follow it up with -Pactivated-profile-name.

<profiles>

<profile> <!-- H2 server-based DB -->

<id>h2srv</id>

<properties>

<jdbc.driver>org.h2.Driver</jdbc.driver>

<jdbc.url>jdbc:h2:tcp://${db.host}:9092/./h2db/ejava</jdbc.url>

<jdbc.user>sa</jdbc.user>

<jdbc.password/>

<hibernate.dialect>org.hibernate.dialect.H2Dialect</hibernate.dialect>

</properties>

<dependencies>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<version>${h2db.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

</profile>

<profile> <!-- H2 file-based DB -->

<id>h2db</id>

<activation>

<property>

<name>!jdbcdb</name>

</property>

</activation>

<properties>

<jdbc.driver>org.h2.Driver</jdbc.driver>

Page 15: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Summary

9

<jdbc.url>jdbc:h2:${basedir}/target/h2db/ejava</jdbc.url>

<jdbc.user>sa</jdbc.user>

<jdbc.password/>

<hibernate.dialect>org.hibernate.dialect.H2Dialect</hibernate.dialect>

</properties>

<dependencies>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<version>${h2db.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

</profile>

</profiles>

Note

Profiles can be used to control which options are enabled at build time to make

the module more portable. I also use them to help identify which dependencies

are brought in for what reason -- especially for profiles that are configure to

always activate.

12.Perform a test of your pom.xml by issuing a sample build command. All should complete even

though there is nothing yet in your source tree.

$ mvn clean test

2.1. Summary

In this chapter you created a core Maven project definition with the ability to resolve dependencies,

build, and potentially test a JPA module. At this point you have an empty but valid Maven project/

module. In the following chapters we will add more artifacts to make to build something useful.

Page 16: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

10

Page 17: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 3.

11

Setup Database SchemaThis chapter will take you through steps that will populate your database with a (simple) database

schema. A database schema is required by any module that directly interacts with a RDMBS. The

JPA provider can automatically generate a database schema but that is generally restricted to

early development and quick prototypes. A module within the data tier will ultimately be responsible

for providing a separate artifact the create and/or migrate the schema from version-to-version.

That is typically finalized by humans knowledgable about particular databases and can be aided

by tool(s) we introduce in this exercise.

1. Create a set of ddl scripts in src/main/resources/ddl to handle creating the schema, deleting

rows in the schema, and dropping tables in the schema. Make sure each script has the word

"create", "delete", or "drop" in its file name to match some search strings we'll use later. Have

the database generate a value for the primary key. That value should not be allowed to be null.

`-- src

|-- main

| |-- java

| `-- resources

| |-- ddl

| | |-- emauto_create.ddl

| | |-- emauto_delete.ddl

| | `-- emauto_drop.ddl

`-- test

|-- java

`-- resources

Note

We could actually skip this step and have the persistence provider create the

table for us. That approach is great for quick Java-first prototypes. However,

creating the schema outside of the persistence provider is a more realistic

scenario for larger developments.

# src/main/resources/ddl/emauto_create.ddl

CREATE TABLE EM_AUTO (

ID BIGINT generated by default as identity (start with 1) not null,

MAKE VARCHAR(32),

MODEL VARCHAR(32),

COLOR VARCHAR(32),

MILEAGE INT,

CONSTRAINT em_autoPK PRIMARY KEY(ID)

)

# src/main/resources/ddl/emauto_delete.ddl

DELETE FROM EM_AUTO;

# src/main/resources/ddl/emauto_drop.ddl

Page 18: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 3. Setup Database Schema

12

DROP TABLE EM_AUTO if EXISTS;

2. You can perform a sanity check of the above scripts by pasting them into the DB UI SQL area

and executing.

3. Add the standard database setup and teardown scripts. This allows us to create a legacy

database schema and write classes that map to that schema. We will later have the persistence

provider create the schema for us when we are in quick prototype mode. First create the

reusable portion of the definition in the pluginManagement section. This will define the version,

database dependencies, and property information for all to inherit.

<build>

<pluginManagement>

<plugins>

...

<plugin>

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<version>${sql-maven-plugin.version}</version>

<dependencies>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<version>${h2db.version}</version>

</dependency>

</dependencies>

<configuration>

<username>${jdbc.user}</username>

<password>${jdbc.password}</password>

<driver>${jdbc.driver}</driver>

<url>${jdbc.url}</url>

</configuration>

</plugin>

</plugins>

</pluginManagement>

</build>

4. Next add the potentially project-specific portion to a build-plugins-plugin section that would

normally be in the child module. However, when you add this to the module -- do so within a

profile that is wired to always run except when the system property -DskipTests is defined. This

is a standard maven system property that builders use to build the module and bypass both

unit and integration testing. By honoring the property here -- our module will only attempt to

work with the database if we ware not skipping tests. Note the !bang-not character means "the

absence of this system property".

<profiles>

...

<profile>

<id>testing</id>

Page 19: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

13

<activation>

<property>

<name>!skipTests</name>

</property>

</activation>

<build>

<plugins>

<plugin>

<!-- runs schema against the DB -->

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<executions>

<!-- place execution elements here -->

</executions>

</plugin>

</plugins>

</build>

</profile>

</profiles>

5. Configure the sql-maven-plugin executions element to run any drop scripts in the source tree

before running tests.

<execution>

<id>drop-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

<onError>continue</onError>

</configuration>

</execution>

Note

Note that we are controlling when the scripts are executed using the phase

element. This is naming a well known Maven lifecycle phase for the build.

6. Configure the sql-maven-plugin executions element to run any scripts from the source tree to

create schema before running tests.

Page 20: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 3. Setup Database Schema

14

<execution>

<id>create-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*create*.ddl</include>

</includes>

</fileset>

<print>true</print>

</configuration>

</execution>

7. Configure the sql-maven-plugin executions element to run any populate scripts from the source

tree to add rows to the database before running tests.

<execution>

<id>populate-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>test/resources/ddl/**/*populate*.ddl</include>

</includes>

</fileset>

</configuration>

</execution>

8. Configure the sql-maven-plugin executions element to run any drop scripts after testing. You

may want to comment this out if you want to view database changes in a GUI after the test.

<execution>

<id>drop-db-after-test</id>

<phase>test</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

Page 21: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Summary

15

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

</configuration>

</execution>

9. Build and run the tests. The schema should show up in the DB UI.

$mvn clean test -P\!h2db -Ph2srv

Note

Remember to turn off (-P!profile-name) the embedded profile (h2db) if active by

default and turn on the server profile (h2srv) if you wish to use the server and DB

UI while the unit test is running. The DB UI can only inspect the embedded file

once all active clients close the file. The backslash is only needed for commands

from the bash shell.

3.1. Summary

In this chapter you added a (trivial) schema definition for your module. This schema definition

was used to manage (create, delete, and drop) the schema within the database. Although we will

show that schema can be generated automatically by the JPA persistence provider and managed

at runtime -- this feature is only feasible for functional unit testing and quick prototypes. Any real

application will require a separate database schema artifact finalized by developers to be tuned

appropriately for the target database.

Page 22: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

16

Page 23: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 4.

17

Add SQL TuningIn this chapter we are going to add tuning aspects to the schema put in place above. Examples of

this include any indexes we believe would enhance the query performance. This example is still

quite simple and lacks enough context to determine what would and would not be a helpful index.

Simply treat this exercise as a tutorial in putting an index in place when properly identified. Adding

the physical files mentioned here could be considered optional if all schema is hand-crafted. You

control the contents of each file in a 100% hand-crafted DDL solution. However, for those cases

where auto-generated schema files are created, you may want a separate set of files designated

for "tuning" the schema that was auto-generated. We will demonstrate using two extra files to

create/drop database indexes.

1. Add a file to add database indexes for your schema

# src/main/resources/ddl/emauto_tuningadd.ddl

CREATE INDEX EM_AUTO_MAKEMODEL ON EM_AUTO(MAKE, MODEL);

2. Wire this new file into your SQL plugin definition for creating schema. Have it run after your table

creates. Add an "orderFile" [https://www.mojohaus.org/sql-maven-plugin/execute-mojo.html]

element to the configuration to specify to the plugin that you wish the files be executed in a

specific order. Otherwise the order will be non-deterministic and the tuning may get executed

before the schema is created.

<execution>

<id>create-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<orderFile>ascending</orderFile>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*create*.ddl</include>

<include>main/resources/ddl/**/*tuningadd*.ddl</include>

</includes>

</fileset>

<print>true</print>

</configuration>

</execution>

3. Add a file to augment the drop script and remove indexes from your schema

# src/main/resources/ddl/emauto_tuningremove.ddl

DROP INDEX EM_AUTO_MAKEMODEL if exists;

Page 24: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 4. Add SQL Tuning

18

4. Wire this new file into your SQL plugin definition for dropping schema. Have it run before

your table drops. Add an "orderFile" [https://www.mojohaus.org/sql-maven-plugin/execute-

mojo.html] element to the configuration to specify to the plugin that you wish the files be

executed in a specific order.

<configuration>

<autocommit>true</autocommit>

<orderFile>decending</orderFile>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*tuningremove*.ddl</include>

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

<onError>continue</onError>

</configuration>

5. Build the schema for your module

$ mvn clean process-test-classes

...

[INFO] --- sql-maven-plugin:1.4:execute (drop-db-before-test) @ entityMgrEx ---

[INFO] Executing file: .../src/main/resources/ddl/emauto_drop.ddl

[INFO] Executing file: .../src/main/resources/ddl/emauto_tuningremove.ddl

[INFO] 2 of 2 SQL statements executed successfully

[INFO]

[INFO] --- sql-maven-plugin:1.4:execute (create-db-before-test) @ entityMgrEx ---

[INFO] Executing file: .../src/main/resources/ddl/emauto_create.ddl

[INFO] Executing file: .../entityMgrEx/src/main/resources/ddl/emauto_tuningadd.ddl

[INFO] 2 of 2 SQL statements executed successfully

4.1. Summary

In this chapter you added additional schema files to the overall build process by assuming core

schema files may be generated by the persistence provider and additional tweaks may need to

be added within the development environment to complete testing.

Page 25: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 5.

19

JPA Persistence Unit SetupThis chapter will add an entity class, the persistence.xml, and associated property file to define

the persistence unit.

The entity class represents one or more tables in the database and each instance of the entity

class represents a specific row in those tables.

The persistence.xml defines a JPA persistence unit (along with other related XML files and entity

class annotations). Instances of a persistence unit is called a persistence context. Instances of

the persistence unit are accessed through an EntityManager.

`-- src

|-- main

| |-- java

| | `-- myorg

| | `-- entitymgrex

| | `-- Auto.java

| `-- resources

| `-- META-INF

| `-- persistence.xml

`-- test

|-- java

`-- resources

`-- hibernate.properties

1. Create a (Plain Old Java Object (POJO)) class to represent an automobile. Use class

annotations to provide the following:

# src/main/java/myorg/entitymgrex/Auto.java

package myorg.entitymgrex;

import java.io.Serializable;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GenerationType;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.Table;

@Entity @Table(name="EM_AUTO")

public class Auto implements Serializable {

private static final long serialVersionUID = 1L;

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)

private long id;

private String make;

private String model;

private String color;

private int mileage;

public Auto(){}

public Auto(int id) { this.id=id; }

Page 26: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 5. JPA Persistence Un...

20

public long getId() { return id; }

//more getter/setters go here

}

Note

@Entity, @Id, and a default constructor are the only requirements on an entity

class. The implementation of java.io.Serializable is not a JPA requirement but

will be leveraged by a later example within this exercise.

2. Add the remaining setter/getter methods to the class. If you are using Eclipse to author the

class -- right click->Source->Generate Getters and Setters will generate all of this for you. Since

we are using generated primary key values, there is no immediate need for a constructor to set

the id. If you add this later, remember to also add a default constructor, which was removed by

the compiler when you manually add the first constructor.

public void setMake(String make) {

this.make = make;

}

public int getMileage() { return mileage; }

public void setMileage(int mileage) {

this.mileage = mileage;

}

public String getModel() { return model; }

public void setModel(String model) {

this.model = model;

}

public String getColor() { return color; }

public void setColor(String color) {

this.color = color;

}

3. You may also want to add a public toString():String method to conveniently print your Auto

objects. Eclipse can also generate that on demand and configurable.

@Override

public String toString() {

StringBuilder builder = new StringBuilder();

builder

.append("id=").append(id)

.append(", make=").append(make)

.append(", model=").append(model)

.append(", color=").append(color)

.append(", mileage=").append(mileage);

return builder.toString();

}

4. Create a META-INF/persistence.xml file to define the persistence unit for our jar file.

Page 27: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

21

• persistence-unit name: must match what we place in our JUnit test

• provider: specify that this persistence unit is defined for the

org.hibernate.jpa.HibernatePersistenceProvider provider.

• define provider-specific properties that tell the provider how to obtain a connection to the

database as well as some other configuration properties.

Note

The technique to add the provider-specific properties includes somewhat

sensitive information like user credentials. If we place them in the

persistence.xml file within the src/main tree, these properties will become part

of our deployed artifact. To avoid this, we will define them in a separate

hibernate.properties file placed in the src/test tree.

# src/main/resources/META-INF/persistence.xml

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

<persistence xmlns="http://java.sun.com/xml/ns/persistence"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/

persistence_2_0.xsd" version="2.0">

<persistence-unit name="entityMgrEx">

<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<properties>

<!-- defined in src/test/resources/hibernate.properties -->

</properties>

</persistence-unit>

</persistence>

5. Create a hibernate.properties file in src/test/resources to hold information we want to support

testing, but may not want to be part of the deployed artifact. Leave the volatile values as

variables so they can be expanded into the target tree during compile time.

• the variables will be filled in during the build process using "filtering" and the resources plugin.

• the show and format_sql options are only turned on during early development and debug.

• the jdbc.batch_size property set to 0 is also used during debug. Setting it to this value will

eliminate any batching of SQL commands, allowing errors about the commands to be better

reported to the developer.

# src/test/resources/hibernate.properties

hibernate.connection.url=${jdbc.url}

hibernate.connection.driver_class=${jdbc.driver}

hibernate.connection.username=${jdbc.user}

hibernate.connection.password=${jdbc.password}

hibernate.dialect=${hibernate.dialect}

#hibernate.hbm2ddl.auto=create

hibernate.hbm2ddl.import_files=/ddl/emauto-tuningdrop.ddl,/ddl/emauto-tuning.ddl

hibernate.show_sql=true

hibernate.format_sql=true

Page 28: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 5. JPA Persistence Un...

22

#hibernate.jdbc.batch_size=0

6. Make sure your project still builds. Your area should look something like the following after the

build.

$ mvn clean install -P\!h2db -Ph2srv

|-- pom.xml

|-- src

| |-- main

| | |-- java

| | | `-- myorg

| | | `-- entitymgrex

| | | `-- Auto.java

| | `-- resources

| | |-- ddl

| | | |-- emauto_create.ddl

| | | |-- emauto_delete.ddl

| | | |-- emauto_drop.ddl

| | | |-- emauto_tuningadd.ddl

| | | `-- emauto_tuningremove.ddl

| | `-- META-INF

| | `-- persistence.xml

| `-- test

| `-- resources

| `-- hibernate.properties

`-- target

|-- classes

| |-- ddl

| | |-- emauto_create.ddl

| | |-- emauto_delete.ddl

| | |-- emauto_drop.ddl

| | |-- emauto_tuningadd.ddl

| | `-- emauto_tuningremove.ddl

| |-- META-INF

| | `-- persistence.xml

| `-- myorg

| `-- entitymgrex

| `-- Auto.class

...

`-- test-classes

`-- hibernate.properties

7. You should also check that your hibernate.properties file was filtered by your

build.testResources definition provided earlier. The variable definitions within your src/test/

resources source file(s) should be replaced with property values from your environment.

$ more src/test/resources/hibernate.properties target/test-classes/hibernate.properties

::::::::::::::

src/test/resources/hibernate.properties

::::::::::::::

hibernate.dialect=${hibernate.dialect}

Page 29: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Summary

23

hibernate.connection.url=${jdbc.url}

hibernate.connection.driver_class=${jdbc.driver}

hibernate.connection.password=${jdbc.password}

hibernate.connection.username=${jdbc.user}

#hibernate.hbm2ddl.auto=create

hibernate.show_sql=true

hibernate.format_sql=true

#hibernate.jdbc.batch_size=0

::::::::::::::

target/test-classes/hibernate.properties

::::::::::::::

hibernate.dialect=org.hibernate.dialect.H2Dialect

hibernate.connection.url=jdbc:h2:tcp://127.0.0.1:9092/./h2db/ejava

hibernate.connection.driver_class=org.h2.Driver

hibernate.connection.password=

hibernate.connection.username=sa

#hibernate.hbm2ddl.auto=create

#hibernate.hbm2ddl.import_files=/ddl/emauto-tuningdrop.ddl,/ddl/emauto-tuning.ddl

hibernate.show_sql=true

hibernate.format_sql=true

#hibernate.jdbc.batch_size=0

5.1. Summary

In this chapter you defined a JPA entity class, persistence unit, and properties specific to your

database instance. With these tackled, you have the core building blocks in place to begin

instantiating the JPA EntityManager in the next chapter. You will notice that the specification

of your database properties came from your Maven pom properties instead of hard-coded into

individual files. This leveraged the filtering feature of resource files during the build. In the last

chapter of this exercise you will be asked to re-factor the Maven database properties into a parent

Maven project to be re-used across several projects.

Page 30: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

24

Page 31: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 6.

25

Setup JPA TestCaseThis chapter will create a JUnit test case that will instantiate an EntityManager, perform some

basic operations, and log information about the tests.

`-- src

`-- test

|-- java

| `-- myorg

| `-- entitymgrex

| `-- EntityMgrTest.java

`-- resources

`-- log4j.xml

1. Create a JUnit test case to hold your test code. The following is an example of a 4.x JUnit test

case that uses @Annotations.

# src/test/java/myorg/entitymgrex/EntityMgrTest.java

package myorg.entitymgrex;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import javax.persistence.EntityManager;

import javax.persistence.EntityManagerFactory;

import javax.persistence.Persistence;

import javax.persistence.Query;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import static org.junit.Assert.*;

import org.junit.After;

import org.junit.AfterClass;

import org.junit.Before;

import org.junit.BeforeClass;

import org.junit.Test;

public class EntityMgrTest {

private static final Logger log = LoggerFactory.getLogger(EntityMgrTest.class);

@Test

public void testTemplate() {

logger.info("testTemplate");

}

}

2. Provide a setUpClass() method that runs once before all tests that can create the entity

manager. This method must be static.

Page 32: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 6. Setup JPA TestCase

26

private static final String PERSISTENCE_UNIT = "entityMgrEx";

private static EntityManagerFactory emf;

@BeforeClass

public static void setUpClass() {

log.debug("creating entity manager factory");

emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);

}

3. Provide a setUp() method that will be called before each testMethod is executed. Have this

method create an entity manager for the tests to use.

private EntityManager em;

@Before

public void setUp() throws Exception {

log.debug("creating entity manager");

em = emf.createEntityManager();

//cleanup();

}

4. Provide a tearDown() method that will be called after each testMethod. Have this flush all

remaining items in the persistence context to the database and close the entity manager.

@After

public void tearDown() throws Exception {

if (em!=null) {

logger.debug("tearDown() started, em={}", em);

em.getTransaction().begin();

em.flush();

//logAutos();

em.getTransaction().commit();

em.close();

logger.debug("tearDown() complete, em={}", em);

em=null;

}

}

5. Provide a tearDownClass() method that will be called after all testMethods have completed.

This method must be static and should close the entity manager factory.

@AfterClass

public static void tearDownClass() {

if (emf!=null) {

logger.debug("closing entity manager factory");

emf.close();

emf=null;

}

}

Page 33: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

27

6. Add in a logAutos() method to query and print all autos in the database. Do this after flushing

the entity manager in the tearDown() method so you can see the changes from the previous

test. The following example uses the entity manager to create an ad-hoc EJB-QL statement.

@After

public void tearDown() throws Exception {

...

em.flush();

logAutos();

em.getTransaction().commit();

...

}

public void logAutos() {

Query query = em.createQuery("select a from Auto as a");

for (Object o: query.getResultList()) {

logger.info("EM_AUTO: {}", o);

}

}

7. You might also want to add a cleanup() to clear out the Auto table between tests. The example

below uses the entity manager to create a native SQL statement.

@Before

public void setUp() throws Exception {

...

em = emf.createEntityManager();

cleanup();

}

public void cleanup() {

em.getTransaction().begin();

Query query = em.createNativeQuery("delete from EM_AUTO");

int rows = query.executeUpdate();

em.getTransaction().commit();

logger.info("removed {} rows", rows);

}

8. Add a log4j.xml file to src/test/resources that has your desired settings. The one below produces

less timestamp information at the console and more details in the logfile.

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

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration

xmlns:log4j="http://jakarta.apache.org/log4j/"

debug="false">

<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">

<param name="Target" value="System.out"/>

<layout class="org.apache.log4j.PatternLayout">

<param name="ConversionPattern"

value="(%F:%M:%L) -%m%n"/>

Page 34: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 6. Setup JPA TestCase

28

</layout>

</appender>

<appender name="logfile" class="org.apache.log4j.RollingFileAppender">

<param name="File" value="target/log4j-out.txt"/>

<param name="Append" value="false"/>

<param name="MaxFileSize" value="100KB"/>

<param name="MaxBackupIndex" value="1"/>

<layout class="org.apache.log4j.PatternLayout">

<param name="ConversionPattern"

value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>

</layout>

</appender>

<logger name="myorg">

<level value="debug"/>

<appender-ref ref="logfile"/>

</logger>

<root>

<priority value="fatal"/>

<appender-ref ref="CONSOLE"/>

</root>

</log4j:configuration>

Note

Although it might be a bit entertaining to set the priority of the root appender to

debug to see everything the persistence provider has to say, it is quite noisy.

Consider changing to root priority to fatal so that a majority of the log statements

are yours.

9. You should be able to build and test your module at this time.

$ mvn clean test

Running myorg.entitymgrex.EntityMgrTest

(EntityMgrTest.java:setUpClass:25) -creating entity manager factory

(EntityMgrTest.java:setUp:31) -creating entity manager

Hibernate:

delete

from

EM_AUTO

(EntityMgrTest.java:cleanup:58) -removed 0 rows

(EntityMgrTest.java:testTemplate:75) -testTemplate

(EntityMgrTest.java:tearDown:39) -tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@3e52a475

Hibernate:

select

auto0_.id as id0_,

auto0_.color as color0_,

auto0_.make as make0_,

auto0_.mileage as mileage0_,

Page 35: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

29

auto0_.model as model0_

from

EM_AUTO auto0_

(EntityMgrTest.java:tearDown:45) -tearDown() complete, em=org.hibernate.ejb.EntityManagerImpl@3e52a475

(EntityMgrTest.java:tearDownClass:69) -closing entity manager factory

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.337 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

...

[INFO] BUILD SUCCESS

Raise org.hibernate verbosity to help debug errors

If you tests failed and there is no key information printed, try raising the verbosity

for all org.hibernate classes to DEBUG.

# src/test/resources/log4j.xml

<logger name="org.hibernate">

<level value="trace"/>

<appender-ref ref="logfile"/>

</logger>

10.Check that you have the following artifacts in your project tree.

|-- pom.xml

|-- src

| |-- main

| | |-- java

| | | `-- myorg

| | | `-- entitymgrex

| | | `-- Auto.java

| | `-- resources

| | |-- ddl

| | | |-- emauto_create.ddl

| | | |-- emauto_delete.ddl

| | | |-- emauto_drop.ddl

| | | |-- emauto_tuningadd.ddl

| | | `-- emauto_tuningremove.ddl

| | `-- META-INF

| | `-- persistence.xml

| `-- test

| |-- java

| | `-- myorg

| | `-- entitymgrex

| | `-- EntityMgrTest.java

| `-- resources

| |-- hibernate.properties

| `-- log4j.xml

`-- target

|-- antrun

| `-- build-main.xml

Page 36: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 6. Setup JPA TestCase

30

|-- classes

| |-- ddl

| | |-- emauto_create.ddl

| | |-- emauto_delete.ddl

| | |-- emauto_drop.ddl

| | |-- emauto_tuningadd.ddl

| | `-- emauto_tuningremove.ddl

| |-- META-INF

| | `-- persistence.xml

| `-- myorg

| `-- entitymgrex

| `-- Auto.class

|-- generated-sources

| `-- annotations

|-- generated-test-sources

| `-- test-annotations

|-- h2db

| `-- ejava.h2.db

|-- log4j-out.txt

|-- maven-status

| `-- maven-compiler-plugin

| |-- compile

| | `-- default-compile

| | |-- createdFiles.lst

| | `-- inputFiles.lst

| `-- testCompile

| `-- default-testCompile

| |-- createdFiles.lst

| `-- inputFiles.lst

|-- surefire-reports

| |-- myorg.entitymgrex.EntityMgrTest.txt

| `-- TEST-myorg.entitymgrex.EntityMgrTest.xml

`-- test-classes

|-- hibernate.properties

|-- log4j.xml

`-- myorg

`-- entitymgrex

`-- EntityMgrTest.class

6.1. Summary

In this chapter you created an EntityManager, managed the transaction, and closed the

EntityManager within the JUnit framework set of callbacks. JUnit will create a new instance of

the class and execute @Before, @Test, @After in that order for each @Test. @BeforeClass is

run before the first @Before/@Test and @AfterClass is run after the last @Test/@After and must

be static.

There are numerous ways to setup the transaction properties. Some make it a practice to rollback

the transaction as a part of each @After (after an em.flush() of course). There is nothing wrong with

managing the transaction within the @Test for certain tests but make it a point *NOT* to attempt to

manage the transaction within code placed in the src/main tree without some careful consideration.

JavaEE is a framework and transaction management is a key part of that framework. You would be

Page 37: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Summary

31

outside the framework if you attempt to directly manage a tranaction in your src/main production

code. Much more on that later.

Page 38: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

32

Page 39: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 7.

33

Ready Project for Import into EclipseOver the years/versions, Eclipse has progressed from being ignorant of Maven (with all integration

coming from the Maven side) to being very much integrated with Maven. In that later/integrated

mode, Eclipse will try really hard to do the right thing within Eclipse for what was defined to be done

outside of Eclipse. For example, Eclipse will turn Maven dependencies directly into an Eclipse

build path. There exists, however, some plugins that Eclipse has yet to learn about and will alert

you to that fact. Many of these have no role within Eclipse and you simply need to explicitly give

Eclipse instruction to ignore the plugin. Luckily these cases get fewer and fewer each year and

Eclipse will update your pom.xml with the necessary configuration when it is needed.

• Import the project into Eclipse using "Existing Maven Projects" option. You should see an error

for the maven-sql-plugin. Ignore the error and continue with the import. We will address the

error in the next step.

• Add the following profile to your pom.xml. The profile is activated when the m2e.version property

is defined -- which is a property m2e (Maven To Eclipse) sets within Eclipse.

<profiles>

...

<!-- tell Eclipse what to do with some of the plugins -->

<profile>

<id>m2e</id>

<activation>

<property>

<name>m2e.version</name>

</property>

</activation>

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.eclipse.m2e</groupId>

<artifactId>lifecycle-mapping</artifactId>

<version>1.0.0</version>

<configuration>

<lifecycleMappingMetadata>

<pluginExecutions>

<pluginExecution>

<pluginExecutionFilter>

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<versionRange>[1.0.0,)</versionRange>

<goals>

<goal>execute</goal>

</goals>

</pluginExecutionFilter>

<action>

<ignore />

</action>

</pluginExecution>

Page 40: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 7. Ready Project for ...

34

</pluginExecutions>

</lifecycleMappingMetadata>

</configuration>

</plugin>

</plugins>

</pluginManagement>

</build>

</profile>

...

</profiles>

The red error marks should have cleared from the pom.xml editor. The above provide is

activated when the "m2e.version" is present within Eclipse and tells Eclipse to ignore the sql-

maven-plugin.

7.1. Summary

In this chapter you imported your JPA project into Eclipse and took care of any issues getting

Eclipse to understand what to do with plugins that it did not understand or need to understand.

Page 41: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 8.

35

Test EntityManager MethodsThis chapter will demonstrate various methods to perform create, read, update, and delete

(CRUD) operations on the database using the EntityManager, the persistence unit/context, and

the entity class.

Note

The following changes are all made to the EntityMgrTest.java JUnit test class.

Everything is being done within this file to keep things simple. This test case is

playing the role of the business and persistence (Data Access Object (DAO)) logic.

1. add a testCreate() method to test the functionality of EntityManager.create(). This will add an

object to the database once associated with a transaction.

@Test

public void testCreate() {

logger.info("testCreate");

Auto car = new Auto();

car.setMake("Chrysler");

car.setModel("Gold Duster");

car.setColor("Gold");

car.setMileage(60*1000);

logger.info("creating auto: {}", car);

em.persist(car);

}

-testCreate

-creating auto:myorg.entitymgrex.Auto@140984b, id=0, make=Chrysler, model=Gold Duster, color=Gold,

mileage=60000

-tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@3ac93e

-EM_AUTO:myorg.entitymgrex.Auto@140984b, id=1, make=Chrysler, model=Gold Duster, color=Gold,

mileage=60000

-removed 1 rows

2. add a testMultiCreate() to test creating several objects. This should also help verify that unique

primary keys are being generated.

@Test

public void testMultiCreate() {

logger.info("testMultiCreate");

for(int i=0; i<5; i++) {

Auto car = new Auto();

car.setMake("Plymouth " + i);

car.setModel("Grand Prix");

car.setColor("Green");

car.setMileage(80*1000);

logger.info("creating auto: {}", car);

Page 42: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 8. Test EntityManager...

36

em.persist(car);

}

}

-testMultiCreate

-creating auto:myorg.entitymgrex.Auto@c3e9e9, id=0, make=Plymouth 0, model=Grand Prix, color=Green,

mileage=80000

-creating auto:myorg.entitymgrex.Auto@31f2a7, id=0, make=Plymouth 1, model=Grand Prix, color=Green,

mileage=80000

-creating auto:myorg.entitymgrex.Auto@131c89c, id=0, make=Plymouth 2, model=Grand Prix, color=Green,

mileage=80000

-creating auto:myorg.entitymgrex.Auto@1697b67, id=0, make=Plymouth 3, model=Grand Prix, color=Green,

mileage=80000

-creating auto:myorg.entitymgrex.Auto@24c4a3, id=0, make=Plymouth 4, model=Grand Prix, color=Green,

mileage=80000

-tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@1e9c82e

-EM_AUTO:myorg.entitymgrex.Auto@c3e9e9, id=2, make=Plymouth 0, model=Grand Prix, color=Green,

mileage=80000

-EM_AUTO:myorg.entitymgrex.Auto@31f2a7, id=3, make=Plymouth 1, model=Grand Prix, color=Green,

mileage=80000

-EM_AUTO:myorg.entitymgrex.Auto@131c89c, id=4, make=Plymouth 2, model=Grand Prix, color=Green,

mileage=80000

-EM_AUTO:myorg.entitymgrex.Auto@1697b67, id=5, make=Plymouth 3, model=Grand Prix, color=Green,

mileage=80000

-EM_AUTO:myorg.entitymgrex.Auto@24c4a3, id=6, make=Plymouth 4, model=Grand Prix, color=Green,

mileage=80000

3. add a testFind() to test the ability to find an object by its primary key value.

@Test

public void testFind() {

logger.info("testFind");

Auto car = new Auto();

car.setMake("Ford");

car.setModel("Bronco II");

car.setColor("Red");

car.setMileage(0*1000);

logger.info("creating auto: {}", car);

em.persist(car);

//we need to associate the em with a transaction to get a

//primary key generated and assigned to the auto

em.getTransaction().begin();

em.getTransaction().commit();

Auto car2 = em.find(Auto.class, car.getId());

assertNotNull("car not found:" + car.getId(), car2);

logger.info("found car: {}", car2);

}

-testFind

-creating auto:myorg.entitymgrex.Auto@aae86e, id=0, make=Ford, model=Bronco II, color=Red, mileage=0

-found car:myorg.entitymgrex.Auto@aae86e, id=7, make=Ford, model=Bronco II, color=Red, mileage=0

Page 43: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

37

-tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@97d026

-EM_AUTO:myorg.entitymgrex.Auto@aae86e, id=7, make=Ford, model=Bronco II, color=Red, mileage=0

4. add a getReference() to test the ability to get a reference to an object. With such a shallow

object, this will act much like find().

@Test

public void testGetReference() {

logger.info("testGetReference");

Auto car = new Auto();

car.setMake("Ford");

car.setModel("Escort");

car.setColor("Red");

car.setMileage(0*1000);

logger.info("creating auto: {}", car);

em.persist(car);

//we need to associate the em with a transaction to get a

//primary key generated and assigned to the auto

em.getTransaction().begin();

em.getTransaction().commit();

Auto car2 = em.getReference(Auto.class, car.getId());

assertNotNull("car not found:" + car.getId(), car2);

logger.info("found car: {}", car2);

}

-testGetReference

-creating auto:myorg.entitymgrex.Auto@608760, id=0, make=Ford, model=Escort, color=Red, mileage=0

-found car:myorg.entitymgrex.Auto@608760, id=8, make=Ford, model=Escort, color=Red, mileage=0

-tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@157ea4a

-EM_AUTO:myorg.entitymgrex.Auto@608760, id=8, make=Ford, model=Escort, color=Red, mileage=0

5. add a testUpdate() method to test the ability to have the setter() of a managed ubject update

the database.

@Test

public void testUpdate() {

logger.info("testUpdate");

Auto car = new Auto();

car.setMake("Pontiac");

car.setModel("Gran Am");

car.setColor("Red");

car.setMileage(0*1000);

logger.info("creating auto: {}", car);

em.persist(car);

//we need to associate the em with a transaction to get a

//primary key generated and assigned to the auto

em.getTransaction().begin();

em.getTransaction().commit();

Page 44: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 8. Test EntityManager...

38

for(int mileage=car.getMileage(); mileage<(100*1000); mileage+=20000) {

//here's where the update is done

car.setMileage(mileage);

//commit the update to the database for query

em.getTransaction().begin();

em.getTransaction().commit();

//inspect database for value

int value = getMileage(car.getId());

assertTrue("unexpected mileage:" + value, value == mileage);

logger.info("found mileage: {}", value);

}

}

private int getMileage(long id) {

Query query =

em.createQuery("select a.mileage from Auto as a where a.id=:pk");

query.setParameter("pk", id);

return (Integer)query.getSingleResult();

}

-testUpdate

-creating auto:myorg.entitymgrex.Auto@6a3960, id=0, make=Pontiac, model=Gran Am, color=Red, mileage=0

-found mileage:0

-found mileage:20000

-found mileage:40000

-found mileage:60000

-found mileage:80000

-EM_AUTO:myorg.entitymgrex.Auto@6a3960, id=9, make=Pontiac, model=Gran Am, color=Red, mileage=80000

6. add a testMerge() method to test the ability to perform updates based on the current values of

a detached object. Note that we are using Java serialization to simulate sending a copy of the

object to/from a remote process and then performing the merge based on the updated object.

@Test

public void testMerge() throws Exception {

logger.info("testMerge");

Auto car = new Auto();

car.setMake("Chrystler");

car.setModel("Concord");

car.setColor("Red");

car.setMileage(0*1000);

logger.info("creating auto: {}", car);

car = em.merge(car); //using merge to persist new

//we need to associate the em with a transaction to get a

//primary key generated and assigned to the auto

em.getTransaction().begin();

em.getTransaction().commit();

for(int mileage=(10*1000); mileage<(100*1000); mileage+=20000) {

Page 45: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

39

//simulate sending to remote system for update

Auto car2 = updateMileage(car, mileage);

//verify the object is not being managed by the EM

assertFalse("object was managed", em.contains(car2));

assertTrue("object wasn't managed", em.contains(car));

assertTrue("mileage was same",

car.getMileage() != car2.getMileage());

//commit the update to the database for query

em.merge(car2);

assertTrue("car1 not merged:" + car.getMileage(),

car.getMileage() == mileage);

em.getTransaction().begin();

em.getTransaction().commit();

//inspect database for value

int value = getMileage(car.getId());

assertTrue("unexpected mileage:" + value, value == mileage);

logger.info("found mileage:" + value);

}

}

private Auto updateMileage(Auto car, int mileage) throws Exception {

//simulate sending the object to a remote system

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(car);

oos.close();

//simulate receiving an update to the object from remote system

ByteArrayInputStream bis =

new ByteArrayInputStream(bos.toByteArray());

ObjectInputStream ois = new ObjectInputStream(bis);

Auto car2 = (Auto)ois.readObject();

ois.close();

//here's what they would have changed in remote process

car2.setMileage(mileage);

return car2;

}

-testMerge

-creating auto:myorg.entitymgrex.Auto@147358f, id=0, make=Chrystler, model=Concord, color=Red, mileage=0

-found mileage:10000

-found mileage:30000

-found mileage:50000

-found mileage:70000

-found mileage:90000

-tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@1b4c1d7

-EM_AUTO:myorg.entitymgrex.Auto@147358f, id=10, make=Chrystler, model=Concord, color=Red, mileage=90000

7. add a testRemove() method to verify that we can delete objects from the database.

Page 46: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 8. Test EntityManager...

40

@Test

public void testRemove() {

logger.info("testRemove");

Auto car = new Auto();

car.setMake("Jeep");

car.setModel("Cherokee");

car.setColor("Green");

car.setMileage(30*1000);

logger.info("creating auto: {}", car);

em.persist(car);

//we need to associate the em with a transaction to get a

//primary key generated and assigned to the auto

em.getTransaction().begin();

em.getTransaction().commit();

Auto car2 = em.find(Auto.class, car.getId());

assertNotNull("car not found:" + car.getId(), car2);

logger.info("found car: {}", car2);

//now remove the car

logger.info("removing car: {}", car);

em.remove(car);

//we need to associate the em with a transaction to

//physically remove from database

em.getTransaction().begin();

em.getTransaction().commit();

Auto car3 = em.find(Auto.class, car.getId());

assertNull("car found", car3);

}

-testRemove

-creating auto:myorg.entitymgrex.Auto@28305d, id=0, make=Jeep, model=Cherokee, color=Green, mileage=30000

-found car:myorg.entitymgrex.Auto@28305d, id=11, make=Jeep, model=Cherokee, color=Green, mileage=30000

-removing car:myorg.entitymgrex.Auto@28305d, id=11, make=Jeep, model=Cherokee, color=Green, mileage=30000

8.1. Summary

In this chapter you worked with several of the EntityManager CRUD methods witin the context of

a JUnit test case and Maven project. This should have given you a decent taste of what can be

done with the JPA EntityManager and how to bring this all together within a Maven module. In the

next chapter we will tack on a few more useful features to know.

Page 47: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 9.

41

Automatically Generate Database

SchemaIn a previous chapter, you manually created a set of DDL files to create schema, delete rows from

the schema in the database, and drop the schema from the database. Since your persistence

provider knows how to work with schema, you can optionally get it to create schema for you rather

than generating it manually. Even if you are working with legacy schema (and won't be changing

the database), it is extremely helpful to see the persistence providers version of the schema to

be able to more quickly determine a mis-match in the mapping rather than waiting until runtime

testing. In order to add schema generation to your projects you can add one of the following;

runtime schema generation or compile-time schema generation. Runtime schema generation is

fine for examples and small prototypes, but compile-time generation is suitable for more realistic

development scenarios.

1. runtime schema generation can be added to your project by adding the following property to

your persistence-unit or hibernate.properties. Coldstart your database, comment out your SQL

plugin, and re-run your tests if you want to verify the above will create the database at runtime.

#persistence.xml

<property name="hibernate.hbm2ddl.auto" value="create"/>

#hibernate.properties

hibernate.hbm2ddl.auto=create

2. A set of files for schema can be generated by adding a standard set of properties to the

persistence.xml properties element.

<properties>

<property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/>

<property name="javax.persistence.schema-generation.scripts.create-target" value="target/classes/ddl/

entityMgrEx-JPAcreate.ddl"/>

<property name="javax.persistence.schema-generation.scripts.drop-target" value="target/classes/ddl/entityMgrEx-

JPAdrop.ddl"/>

</properties>

With the above configuration in place, the persistence unit will create two files in the target/

classes/ddl directory that represent the JPA provider's view of the mapping.

target/classes/ddl/

|-- emauto_create.ddl

|-- emauto_delete.ddl

|-- emauto_drop.ddl

|-- emauto_tuningadd.ddl

|-- emauto_tuningremove.ddl

|-- entityMgrEx-JPAcreate.ddl <== generated

`-- entityMgrEx-JPAdrop.ddl <== by the persistence unit

Page 48: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 9. Automatically Gene...

42

The primary downfall in this approach is that the schema is generated too late for us to use the

maven plugin to populate schema and it will execute this behavior all the way into production.

3. compile-time schema generation can be moved forward in the build cycle by instantiating the

persistence unit twice; once in a small program designed only to generate schema and once

for our unit tests. I have wrapped that small program in a Maven plugin which we can install

in our pom. It can be configured some. However, since I wrote it for use with this course -- it

pretty much does what we want without much configuration.

Add the following plugin definition to the pluginManagement section of your pom.xml. This will

define the core behavor of the jpa-schemagen-maven-plugin to execute the generate goal. By

default it executes during the process-test-classes phase.

<build>

<pluginManagement>

<plugins>

...

<plugin>

<groupId>info.ejava.utils.jpa</groupId>

<artifactId>jpa-schemagen-maven-plugin</artifactId>

<version>${ejava.version}</version>

<executions>

<execution>

<goals>

<goal>generate</goal>

</goals>

</execution>

</executions>

</plugin>

...

</plugins>

</pluginManagement>

</build>

4. Add the following active declaration to you pom to activate the plugin and fill in the module-

specifics. We could optionally add it to the database profiles.

...

</pluginManagement>

<plugins>

<plugin>

<artifactId>jpa-schemagen-maven-plugin</artifactId>

<groupId>info.ejava.utils.jpa</groupId>

<configuration>

<persistenceUnit>entityMgrEx</persistenceUnit>

</configuration>

</plugin>

</plugins>

</build>

Page 49: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

43

5. Build your module and notice the generated JPA.ddl files

$ mvn clean process-test-classes

...

[INFO] --- jpa-schemagen-maven-plugin:5.0.0-SNAPSHOT:generate (default) @ entityMgrEx ---

[INFO] Generating database schema for: entityMgrEx

[INFO] removing existing target file:/Users/jim/proj/784/entityMgrEx/target/classes/ddl/entityMgrEx-drop.ddl

[INFO] removing existing target file:/Users/jim/proj/784/entityMgrEx/target/classes/ddl/entityMgrEx-create.ddl

Aug 14, 2018 10:28:50 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation

INFO: HHH000204: Processing PersistenceUnitInfo [

name: entityMgrEx

...]

Aug 14, 2018 10:28:50 PM org.hibernate.Version logVersion

...

INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@10850d17'

...

---

---

target/classes/ddl/

|-- emauto_create.ddl

|-- emauto_delete.ddl

|-- emauto_drop.ddl

|-- emauto_tuningadd.ddl

|-- emauto_tuningremove.ddl

|-- entityMgrEx-JPAcreate.ddl <== generated thru

|-- entityMgrEx-JPAdrop.ddl <===== configuration in persistence.xml

|-- entityMgrEx-create.ddl <== generated thru

`-- entityMgrEx-drop.ddl <===== plugin we just added

6. (Optionally) update your SQL plugin defintion added in previous chapter to reference the

dynamically generated schema in the target tree.

7. (Optionally) update your persistence.xml to turn off schema generation from within all uses of

the persistence unit.

8. Eclipse will again report a plugin error within the pom.xml editor. Add the following definition to

the lifecycle-mapping plugin to have the error ignored.

<pluginExecution>

<pluginExecutionFilter>

<groupId>info.ejava.utils.jpa</groupId>

<artifactId>jpa-schemagen-maven-plugin</artifactId>

<versionRange>[5.0.0-SNAPSHOT,)</versionRange>

<goals>

<goal>generate</goal>

</goals>

</pluginExecutionFilter>

<action>

<ignore/>

</action>

</pluginExecution>

Page 50: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 9. Automatically Gene...

44

9.1. Summary

In this chapter you configured a Maven project to create a set of file artifacts as a part of the

build that represent what the persistence provider believes the database should look like. You

can optionally directly use this as a part of your module's database schema population, use it as

a starting reference to manually create schema, or *most important* gain insight into what the

persistence provider thinks your persistence unit is defined. This will save you some ignorant bliss

that is usually followed by hours of debugging an incorrect mapping.

Page 51: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10.

45

Create JPA Parent POMSince you will likely have many JPA modules in your enterprise application, lets take a moment to

break the current module into a parent and child before you quit. That way you can better visualize

which parts are specific to the child module and which are reusable from a common parent.

1. Create a sibling module called ../jpa-parent

$ mkdir ../jpa-parent

2. Add the module definition (../jpa-parent/pom.xml)

<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>myorg.jpa</groupId>

<artifactId>jpa-parent</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>pom</packaging>

<name>JPA Parent POM</name>

<description>

This parent pom is intended to provide common and re-usable

definitions and constructs across JPA projects.

</description>

</project>

3. Add the following parent declaration to your existing module. The relativePath is only useful if

you find yourself changing the parent pom on a frequent basis. Otherwise the parent module

can be found in the localRepository once it has been installed.

<parent>

<groupId>myorg.jpa</groupId>

<artifactId>jpa-parent</artifactId>

<version>1.0-SNAPSHOT</version>

<relativePath>../jpa-parent</relativePath>

</parent>

<groupId>myorg.jpa</groupId>

<artifactId>entityMgrEx-child</artifactId>

<name>Entity Manager Exercise</name>

4. Verify your project still builds. This will verify your relativePath is correct.

$mvn clean verify

...

[INFO] BUILD SUCCESS

Page 52: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10. Create JPA Parent POM

46

5. Move the following constructs from the entityMgrEx module to the jpa-parent module. These

represent the *passive* definitions that will not directly impact the child module until the child

requests that feature. Your child module should still have the same build and test functionality

except now it should look a little smaller. One could also make a case for moving some of

the SQL/DDL script execution definitions also to the parent -- which would make this module

almost of trivial size.

• properties

• repositories

• dependencyManagement

• pluginManagement

• select profiles

<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>myorg.jpa</groupId>

<artifactId>jpa-parent</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>pom</packaging>

<name>JPA Parent POM</name>

<description>

This parent pom is intended to provide common and re-usable

definitions and constructs across JPA projects.

</description>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<java.source.version>1.8</java.source.version>

<java.target.version>1.8</java.target.version>

<jboss.host>localhost</jboss.host>

<db.host>${jboss.host}</db.host>

<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>

<maven-jar-plugin.version>3.1.0</maven-jar-plugin.version>

<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>

<sql-maven-plugin.version>1.5</sql-maven-plugin.version>

<h2db.version>1.4.197</h2db.version>

<javax.persistence-api.version>2.2</javax.persistence-api.version>

<hibernate-entitymanager.version>5.3.1.Final</hibernate-entitymanager.version>

<junit.version>4.12</junit.version>

<log4j.version>1.2.17</log4j.version>

<slf4j.version>1.7.25</slf4j.version>

<ejava.version>5.0.0-SNAPSHOT</ejava.version>

</properties>

<dependencyManagement>

<dependencies>

Page 53: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

47

<dependency>

<groupId>javax.persistence</groupId>

<artifactId>javax.persistence-api</artifactId>

<version>${javax.persistence-api.version}</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<version>${hibernate-entitymanager.version}</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${slf4j.version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>${slf4j.version}</version>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>${log4j.version}</version>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>${maven-compiler-plugin.version}</version>

<configuration>

<source>${java.source.version}</source>

<target>${java.target.version}</target>

</configuration>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-jar-plugin</artifactId>

<version>${maven-jar-plugin.version}</version>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

Page 54: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10. Create JPA Parent POM

48

<version>${maven-surefire-plugin.version}</version>

<configuration>

<argLine>${surefire.argLine}</argLine>

<systemPropertyVariables>

<property.name>value</property.name>

</systemPropertyVariables>

</configuration>

</plugin>

<plugin>

<groupId>info.ejava.utils.jpa</groupId>

<artifactId>jpa-schemagen-maven-plugin</artifactId>

<version>${ejava.version}</version>

<executions>

<execution>

<goals>

<goal>generate</goal>

</goals>

</execution>

</executions>

</plugin>

<plugin>

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<version>${sql-maven-plugin.version}</version>

<dependencies>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<version>${h2db.version}</version>

</dependency>

</dependencies>

<configuration>

<username>${jdbc.user}</username>

<password>${jdbc.password}</password>

<driver>${jdbc.driver}</driver>

<url>${jdbc.url}</url>

</configuration>

</plugin>

</plugins>

</pluginManagement>

</build>

<profiles>

<profile> <!-- H2 server-based DB -->

<id>h2srv</id>

<properties>

<jdbc.driver>org.h2.Driver</jdbc.driver>

<jdbc.url>jdbc:h2:tcp://${db.host}:9092/./h2db/ejava</jdbc.url>

<jdbc.user>sa</jdbc.user>

<jdbc.password/>

<hibernate.dialect>org.hibernate.dialect.H2Dialect</hibernate.dialect>

Page 55: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

49

</properties>

<dependencies>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<version>${h2db.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

</profile>

<profile> <!-- H2 file-based DB -->

<id>h2db</id>

<activation>

<property>

<name>!jdbcdb</name>

</property>

</activation>

<properties>

<jdbc.driver>org.h2.Driver</jdbc.driver>

<jdbc.url>jdbc:h2:${basedir}/target/h2db/ejava</jdbc.url>

<jdbc.user>sa</jdbc.user>

<jdbc.password/>

<hibernate.dialect>org.hibernate.dialect.H2Dialect</hibernate.dialect>

</properties>

<dependencies>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<version>${h2db.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

</profile>

<profile>

<id>testing</id>

<activation>

<property>

<name>!skipTests</name>

</property>

</activation>

<build>

<plugins>

<plugin>

<!-- runs schema against the DB -->

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<executions>

<!-- place execution elements here -->

<execution>

<id>drop-db-before-test</id>

Page 56: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10. Create JPA Parent POM

50

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<orderFile>decending</orderFile>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*tuningremove*.ddl</include>

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

<onError>continue</onError>

</configuration>

</execution>

<execution>

<id>create-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<orderFile>ascending</orderFile>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*create*.ddl</include>

<include>main/resources/ddl/**/*tuningadd*.ddl</include>

</includes>

</fileset>

<print>true</print>

</configuration>

</execution>

<execution>

<id>populate-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>test/resources/ddl/**/*populate*.ddl</include>

</includes>

</fileset>

</configuration>

</execution>

Page 57: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

51

<!--

<execution>

<id>drop-db-after-test</id>

<phase>test</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

</configuration>

</execution>

-->

</executions>

</plugin>

</plugins>

</build>

</profile>

<!-- tell Eclipse what to do with some of the plugins -->

<profile>

<id>m2e</id>

<activation>

<property>

<name>m2e.version</name>

</property>

</activation>

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.eclipse.m2e</groupId>

<artifactId>lifecycle-mapping</artifactId>

<version>1.0.0</version>

<configuration>

<lifecycleMappingMetadata>

<pluginExecutions>

<pluginExecution>

<pluginExecutionFilter>

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<versionRange>[1.0.0,)</versionRange>

<goals>

<goal>execute</goal>

</goals>

</pluginExecutionFilter>

<action>

<ignore />

</action>

Page 58: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10. Create JPA Parent POM

52

</pluginExecution>

</pluginExecutions>

</lifecycleMappingMetadata>

</configuration>

</plugin>

</plugins>

</pluginManagement>

</build>

</profile>

</profiles>

</project>

6. Leave the following the child project. This is a collection of *active* project constructs.

• plugins

• dependencies

• module-specific properties

• profiles that declare plugins and dependencies

<?xml version="1.0"?>

<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/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>myorg.jpa</groupId>

<artifactId>jpa-parent</artifactId>

<version>1.0-SNAPSHOT</version>

<relativePath>../jpa-parent</relativePath>

</parent>

<groupId>myorg.jpa</groupId>

<artifactId>entityMgrEx</artifactId>

<version>1.0-SNAPSHOT</version>

<name>Entity Manager Exercise</name>

<build>

<!-- filtering will replace URLs, credentials, etc in the

files copied to the target directory and used during testing.

-->

<testResources>

<testResource>

<directory>src/test/resources</directory>

<filtering>true</filtering>

</testResource>

</testResources>

<plugins>

<plugin>

Page 59: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

53

<artifactId>jpa-schemagen-maven-plugin</artifactId>

<groupId>info.ejava.utils.jpa</groupId>

<configuration>

<persistenceUnit>entityMgrEx</persistenceUnit>

</configuration>

</plugin>

</plugins>

</build>

<dependencies>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.persistence</groupId>

<artifactId>javax.persistence-api</artifactId>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

<profiles>

<profile>

<id>testing</id>

<activation>

<property>

<name>!skipTests</name>

</property>

</activation>

<build>

Page 60: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10. Create JPA Parent POM

54

<plugins>

<plugin>

<!-- runs schema against the DB -->

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<executions>

<!-- place execution elements here -->

<execution>

<id>drop-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<orderFile>decending</orderFile>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*tuningremove*.ddl</include>

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

<onError>continue</onError>

</configuration>

</execution>

<execution>

<id>create-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<orderFile>ascending</orderFile>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*create*.ddl</include>

<include>main/resources/ddl/**/*tuningadd*.ddl</include>

</includes>

</fileset>

<print>true</print>

</configuration>

</execution>

<execution>

<id>populate-db-before-test</id>

<phase>process-test-classes</phase>

<goals>

<goal>execute</goal>

</goals>

Page 61: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

55

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>test/resources/ddl/**/*populate*.ddl</include>

</includes>

</fileset>

</configuration>

</execution>

<!--

<execution>

<id>drop-db-after-test</id>

<phase>test</phase>

<goals>

<goal>execute</goal>

</goals>

<configuration>

<autocommit>true</autocommit>

<fileset>

<basedir>${basedir}/src</basedir>

<includes>

<include>main/resources/ddl/**/*drop*.ddl</include>

</includes>

</fileset>

</configuration>

</execution>

-->

</executions>

</plugin>

</plugins>

</build>

</profile>

</profiles>

</project>

7. Verify your project still builds. This will verify your relativePath is correct.

$mvn clean verify

...

[INFO] BUILD SUCCESS

8. Optionally change your jpa-parent dependency to the class examples base parent project.

<parent>

<groupId>info.ejava.examples.build</groupId>

<artifactId>dependencies</artifactId>

<version>x.x.x-SNAPSHOT</version>

<relativePath>build/dependencies/pom.xml</relativePath>

</parent>

Page 62: Java Persistence API: Copyrightwebdev.jhuep.com/~jcs/ejava-javaee/coursedocs/content/pdf/jpa-enti… · • Provide step-by-step instructions for setting up a Maven module for JPA

Chapter 10. Create JPA Parent POM

56

Note

Replace x.x.x-SNAPSHOT with the correct version for class.

Note

It is never a good idea to declare *active* POM constructs in a parent of a multi-

module project unless *ALL* child modules are of the same purpose. Strive for

parent Maven projects to define standards to follow without inserting unecessary

dependencies or other constructs.

10.1. Summary

In this chapter you re-factored your module into a reusable jpa-parent module (that could be

replaced by the class example) and child module. The child is then freed of defining version#s

and other constructs that can be shared across several modules -- allowing smaller child POMs to

be created through templates that produce modules that extend the jpa-parent. Cool. You didn't

want to do that again.

You have now finished all chapters of the Maven and JPA/EntityManager exercise that was geared

at getting you started developing modules that implement the data tier.