Enterprise Java Development@TOPIC@
In 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.
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
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
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.
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>
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>
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
(Optionally) update your SQL plugin defintion added in previous chapter to reference the dynamically generated schema in the target tree.
(Optionally) update your persistence.xml to turn off schema generation from within all uses of the persistence unit.
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>
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.