From 1628bcf6c9290a729352215ee22e5b48fa628c4c Mon Sep 17 00:00:00 2001
From: Kai Moritz
+ The most simple way to configure the plugin is, to put all the
+ hibernate-configuration in a hibernate.properties-file on your
+ classpath. Put the file in the
+ Doing so, the only additionally configuration needed, to activat the plugin
+ is the following entry in the
+ But be aware, that in this case the database-url, that is
+ build in the application is the same that is used while testing, where
+ the database is droped and recreated by the plugin.
+
+ So, you should never fire up this configuration on your production
+ system, or your database might be erased!
+
+
+ Hence, you should specify a different url for testing like in the
+ following snippet:
+
+ Configuration properties, that are set in the
+ Alternatively, it is possible, to configure the plugin via maven-properties.
+ Each relevant configuration-option has a corresponding maven-property
+ (for a full list see the Documentation of the export-Mojo).
+ These are named after the
+ Hibernate JDBC Properties:
+
+ So, instead of writing the hibernate-configuration in the properties-file,
+ like above, you could put it in the
+ Thogether with the plugin-definition from above, the following would
+ be a complete configuration (again, the database-url was overwritten in
+ the plugin-configuration, to be sure to have a separate database for
+ testing):
+
+ A third way for configuring the plugin is the plugin-configuration.
+ The relevant configuration-parameters are:
+
+ The equivalent of the configuration from the last section would look
+ like this:
+
+ The parameter hibernateProperties (name of the hibernate-properties-file
+ to use, defaults to hibernate.properties) can only be configured through
+ this approach.
+
+ For more explanations, see the
+ Documentation of the export-Mojo.
+
+ The configuration is gathered in a fix order:
+
+ If you are in doubt about where a configuration-value comes from, run
+ maven with the debug-output enabled:
+ The plugin-configuration comes last and overwrites everything else.
+ That way, you can be sure, that a configuration-value, that is
+ specified in the plugin-configuration will never be overwritten by any
+ other configuration-method.
+
+ If you realy need to overwrite plugin-configuration-values with
+ maven-properties, you can use maven-properties in the plugin-configuration:
+
+ If you are new to
+ (The
+ Unlike the majority of the maven-plugins,
+ But be warned:
+ The hibernate4-maven-plugin computes MD5-sums for all found annotated
+ classes and stores them together with the generated schema.
+ If no classes were changed or added and the dialect wasn't changed too, it
+ automatically skips the configured schema-export, to speed up the development
+ cycle.
+
+ The plugin signals, that the execution was skipped by setting the maven
+ property
+ If you need the hibernate4-maven-plugin to <never skip execution automatically>,
+ you can force it to do so, if you set the parameter
+ Or you may specify
+ The hibernate4-maven-plugin is a plugin for generating a database-schema
+ from your Hibernate-4-Mappings and create or update your database
+ accordingly.
+ Its main usage is to automatically create and populate a test-database
+ for unit-tests in cooperation with the
+ dbunit-maven-plugin.
+
+ The plugin was designed with three main goals in mind:
+
+ To achieve the first goal, the convention-over-configuration paradigma
+ was applied and the plugin was stuffed with usefull logging-messages.
+ So, if in doubt, just turn on the debugging output with the
+ To achieve the second goal, the precedence in which the configuration
+ locations are consulted was layouted in a way that makes it possible, to
+ prevent overwrites of the wrong database by accident.
+
+ Last but not least, in order to not slow down the development cycle, the
+ hibernate4-maven-plugin only executes the schema-export, if the mapping
+ or the dialect changes (or if you force it to do so).
+
+ For more information about the inspiration to write this tiny plugin,
+ read our blog-article about the hibernate4-maven-plugin.
+
+ Please send your bug-reports, questions or feature-requests directly
+ to the developer.
+
+ Please send your bug-reports, questions or feature-requests directly
+ to the developer.
+
hibernate4-maven-plugin by default scans dependencies in the scope
The default-configuration uses the EXPORT-target of the SchemaExport-Tool.
If you do not need to create a database with the evaluated schema, you can
use the NONE- or the SCRIPT-target.
This can be achieved with the command-line parameter
- <<<-Dhibernate.export.target=SCRIPT>>> or with the following configuration:
-
-------------
-
But even when no database is to be created, hibernate always needs to know
the dialect. Hence, the plugin will fail if this parameter is missing!
-
-Dependency for driver-class XYZ is missing
-
+
One regular problem is the scope of the jdbc-driver-dependency.
It is very unlikely, that this dependency is needed at compile-time.
- So a tidy maven-developer would usually scope it for <<
+ But this will break the execution of the
A quick workaround for this error would be, to delete the runtime-constraint
for the jdbc-driver-dependency.
-
+
A much cleaner way is, to (additionally) ad the dependency, to the
plugin-definition:
-
----------------
-
This is also the best way, if you use a different jdbc-driver for
testing, than in production.
Because otherwise, this dependency will unnecessarily bloat the
runtime-dependencies of your project.
-
-DBUnit {fails} after execution of hibernate4 was skipped because nothing has changed
-
+
If hibernate4-maven-plugin skips its excecution, this may lead to errors in
other plugins.
For example, when importing sample-data in the automatically created database
- with the help of the {{{http://mojo.codehaus.org/dbunit-maven-plugin/}dbunit-plugin}},
- the <<
+ A quick fix to this problem is, to force
hibernate4-maven-plugin to export the schema every time it is running.
But to recreate the database on every testrun may noticeable slow down your
development cycle, if you have to wait for slow IO.
-
+
To circumvent this problem, hibernate4-maven-plugin signals a skipped
- excecution by setting the maven property <<<${hibernate.export.skipped}>>> to
- <<
If one manually drops the database or removes the hsqldb-files, it will not
be recreated by the hibernate4-maven-plugin, because it cannot detect, that
the database needs to be recreated.
@@ -135,35 +134,34 @@ The database will not be recreated after a manual drop/clean
the configuration nor the annotated classes have changed, because an
unnecessary drop-create-cycle might take a long time. The plugin will
report that like this:
-
--------------
+
+ If one always uses
The hibernate4-maven-plugin automatically skips its execution, when
- <<
Background-information for this design-decission can be found on the extra
- page {{{./skip.html}To skip or not to skip: that is the question}}...
+ page To skip or not to skip: that is the question...
+
+ In most use-cases, the hibernate4-maven-plugin is used to create a
+ test-database automatically. In this use-cases, it is very likely, that it
+ will result in mistakes/errors, if the goal is executed, when the tests
+ are skipped.
+ For example, one might manually overwrite the database-url with the url of
+ the production-database, in order to run other tests, like starting a
+ local webserver with the
+ jetty-maven-plugin.
+ If the export-goal would be executed in such a scenario, it might erase the
+ hole production-database, which is not very desireable.
+
+ Because of this, the configuration-parameter
+ If you do not like that, because you need the plugin to always execute the
+ export-goal, even if the tests are skipped you can configure that explicitly,
+ by setting the configuration-parameter
+ Or, if you want the export-goal to be executed by default and to be skipped
+ if you say so, you can bind the value of the configuration-parameter
+
+ This way, the export-goal would be skipped, if you set the property
+ Configuration through a hibernate.properties-File
+ resources
-folder. Maven will put
+ it in the class
-folder of your webapp, where it will be picked up
+ by this plugin as well as by Hibernate 4.
+ plugins
-section of your pom.xml
:
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+</plugin>
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <url><![CDATA[jdbc:mysql://localhost/test-db]]></url>
+ </configuration>
+</plugin>
+ configuration
-section
+ of the plugin-configuration cannnot be overwritten elsewere (for details
+ see Configuration-Method-Precedence).
+ You never can overwrite them by accident when specifying a property on
+ the commandline or in your settings.xml
.
+ Configuration through maven-properties
+
+
+ hibernate.connection.driver_class
hibernate.dialect
hibernate.connection.url
hibernate.connection.username
hibernate.connection.password
properties
-section of your
+ pom.xml
.
+
+<properties>
+ <hibernate.connection.driver_class>org.hsqldb.jdbcDriver</hibernate.connection.driver_class>
+ <hibernate.dialect>org.hibernate.dialect.HSQLDialect</hibernate.dialect>
+ <hibernate.connection.url><![CDATA[jdbc:hsqldb:res:org.my.path.production_db]]></hibernate.connection.url>
+ <hibernate.connection.username>sa</hibernate.connection.username>
+ <hibernate.connection.password></hibernate.connection.password>
+</properties>
+
+...
+
+<plugins>
+
+ ...
+
+ <plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <url><![CDATA[jdbc:hsqldb:target/db/testdb;shutdown=true]]></url>
+ </configuration>
+ </plugin>
+
+<plugins>
+ Configuration through the plugin-configuration
+
+
+ driverClassName
hibernateDialect
url
username
password
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <driverClassName>org.hsqldb.jdbcDriver</driverClassName>
+ <hibernateDialect>org.hibernate.dialect.HSQLDialect</hibernateDialect>
+ <url><![CDATA[jdbc:hsqldb:target/db/fotos;shutdown=true]]></url>
+ <username>sa</username>
+ <password></password>
+ </configuration>
+</plugin>
+ Configuration-Method-Precedence
+
+
+ hibernate.properties
mvn -X hibernate4:export
+ and be aware, that maven-properties can be overwitten on the command-line,
+ in your ~/.m2/settings.xml
and in a profile.
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <password>${my-password-property}</password>
+ </configuration>
+</plugin>
+
+
diff --git a/src/site/xhtml/debugging.xhtml b/src/site/xhtml/debugging.xhtml
new file mode 100644
index 00000000..8f91f3f9
--- /dev/null
+++ b/src/site/xhtml/debugging.xhtml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ hibernate4-maven-plugin
, in many cases, the
+ {Configuration-Method-Precedence} may be the source of configuration
+ errors.
+ To solve this problem, you should run maven with the debugging output
+ enabled.
+ For example, by executing:
+
+mvn -X compile hibernate4:export
+ compile
might be necessary, because hibernate4-maven-plugin
+ has to scan the compiled classes for annotations!)
+ hibernate4-maven-plugin
was
+ designed to give a good many hints, when debugging is enabled.
+ Because, if you do not know, what went wrong, you can't fix it!
+ hibernate4-maven-plugin
tends to be very chatty ;)
+ $\{hibernate.export.skipped\}
to true
.
+ This may be helpful, because other plugins like
+ dbunit-plugin
+ may fail, when the execution is skipped.
+ force
to
+ true
:
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <force>true</force>
+ </configuration>
+</plugin>
+ -Dhibernate.export.force=true
at the command line,
+ if you want to force hibernate4-maven-plugin only once.
+ Hibernate 4 Maven Plugin
+ A simple Plugin for generating a Database-Schema from Hibernate 4 Mapping-Annotations
+
+
+ mvn -X ...
.
+ Documentation
+
+
+ SchemaExport
and SchemaUpdate
, that do
+ the work in the background.
+ Releases
+
+
+
+
diff --git a/src/site/xhtml/issue-tracking.xhtml b/src/site/xhtml/issue-tracking.xhtml
new file mode 100644
index 00000000..f7e68598
--- /dev/null
+++ b/src/site/xhtml/issue-tracking.xhtml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ There is no bug-tracking system set up for this project!
+ Annotated classes in dependencies are not found.
+ compile
. You can configure it to scan dependencies in other
scopes as well. But it scans only direct dependencies. Transitive
dependencies are not scanned for annotated classes. If some of your
annotated classes are hidden in a transitive dependency, you can simply
add that dependency explicitly.
-
-hibernate4-maven-plugin always needs a database-connection
-
+ hibernate4-maven-plugin always needs a database-connection
+ -Dhibernate.export.target=SCRIPT
or with the following configuration:
+
+<configuration>
+ <target>SCRIPT</target>
+</configuration>
+ Dependency for driver-class XYZ is missing
+ runtime
.
+ hibernate4-maven-plugin
.
Since it will not be able to see the needed dependency, it will fail with
an error-message like:
-
----------------
+
[INFO] Gathered hibernate-configuration (turn on debugging for details):
[INFO] hibernate.connection.username = sa
[INFO] hibernate.connection.password =
@@ -58,76 +58,75 @@ Dependency for driver-class XYZ is missing
[INFO] Total time: 2 seconds
[INFO] Finished at: Thu Nov 29 11:31:14 CET 2012
[INFO] Final Memory: 32M/342M
-[INFO] ------------------------------------------------------------------------
----------------
-
+[INFO] ------------------------------------------------------------------------
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>2.2.8</version>
+ </dependency>
+ </dependencies>
+</plugin>
+ DBUnit fails after execution of hibernate4 was skipped because nothing has changed
+ CLEAN_INSERT
-operation may fail because of foreign-key-constraints,
if the database was not recreated, because the hibernate4-maven-plugin has
skipped its excecution.
-
- A quick fix to this problem is, to {{{./force.html}force}}
+ $\{hibernate.export.skipped\}
to
+ true
.
You can configure other plugins to react on this signal.
For example, the dbunit-plugin can be configured to skip its excecution, if
hibernate4-maven-plugin was skipped like this:
-
-------------
-
+<plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>dbunit-maven-plugin</artifactId>
+ <configuration>
+ <skip>${hibernate.export.skipped}</skip>
+ </configuration>
+</plugin>
+ The database will not be recreated after a manual drop/clean
+
[INFO] No modified annotated classes found and dialect unchanged.
-[INFO] Skipping schema generation!
--------------
-
- If one always uses <<
+ mvn clean
for cleanup, this will not happen.
+ Otherwise the recreation must be forced:
+
+mvn hibernate4:export -Dhibernate.export.force=true
+ The hibernate4:export goal is not executed, when tests are skipped
+ maven.test.skip
is set to true
. If you need it to be always
executed, you can configure that explicitly like this:
-
-------------
-
+>plugin<
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
...
-
skip
defaults to the value
+ of the proptery maven.test.skip
. This way, the execution of the
+ hibernate4-maven-plugin is skipped automatically, when the tests are
+ skipped. Think of it as a build-in security-belt.
+ skip
to false:
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ ...
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+</plugin>
+ skip
to a custom property. For example:
+
+<plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ ...
+ <configuration>
+ <skip>${foo.bar}</skip>
+ </configuration>
+</plugin>
+ foo.bar
to true
. For example, if you specify -Dfoo.bar=true
+ on the command-line.
+
- Hence, you should specify a different url for testing like in the + A better approach is, to specify a different url for testing like in the following snippet:
@@ -190,7 +191,7 @@ other configuration-method.- If you realy need to overwrite plugin-configuration-values with + If you need to overwrite plugin-configuration-values with maven-properties, you can use maven-properties in the plugin-configuration:
-- 2.20.1 From f3dabc0e6e3676244986b5bbffdb67d427c8383c Mon Sep 17 00:00:00 2001 From: Kai Moritzexecuted, you can configure that explicitly like this:Date: Mon, 2 Jun 2014 10:31:12 +0200 Subject: [PATCH 05/16] [maven-release-plugin] prepare release hibernate4-maven-plugin-1.0.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a2abed65..b24e83cf 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ hibernate4-maven-plugin Hibernate 4 Maven Plugin Plugin for generating a database-schema from Hibernate-4-Mapping-Annotations -1.0.4-SNAPSHOT +1.0.4 maven-plugin http://juplo.de/hibernate4-maven-plugin -- 2.20.1 From 3dd832edbd50b1499ea6d53e4bcd0ad4c79640ed Mon Sep 17 00:00:00 2001 From: Kai MoritzDate: Mon, 2 Jun 2014 10:31:13 +0200 Subject: [PATCH 06/16] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b24e83cf..df20ab05 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ hibernate4-maven-plugin Hibernate 4 Maven Plugin Plugin for generating a database-schema from Hibernate-4-Mapping-Annotations -1.0.4 +1.0.5-SNAPSHOT maven-plugin http://juplo.de/hibernate4-maven-plugin -- 2.20.1 From 3a3aeaabdb1841faf5e1bf8d220230597fb22931 Mon Sep 17 00:00:00 2001 From: Kai MoritzDate: Sat, 25 Oct 2014 16:52:34 +0200 Subject: [PATCH 07/16] Integrated integration test provided by Claus Graf (clausgraf@gmail.com) --- pom.xml | 4 + src/it/dependency-test/dependent/pom.xml | 26 ++++++ .../main/java/dependent/DependentEntity.java | 17 ++++ src/it/dependency-test/h4mp/pom.xml | 85 +++++++++++++++++++ .../h4mp/src/main/java/h4mp/MainEntity.java | 21 +++++ .../main/resources/META-INF/persistence.xml | 17 ++++ .../src/test/java/h4mp/MainEntityTest.java | 49 +++++++++++ .../test/resources/META-INF/persistence.xml | 23 +++++ src/it/dependency-test/pom.xml | 13 +++ 9 files changed, 255 insertions(+) create mode 100644 src/it/dependency-test/dependent/pom.xml create mode 100644 src/it/dependency-test/dependent/src/main/java/dependent/DependentEntity.java create mode 100644 src/it/dependency-test/h4mp/pom.xml create mode 100644 src/it/dependency-test/h4mp/src/main/java/h4mp/MainEntity.java create mode 100644 src/it/dependency-test/h4mp/src/main/resources/META-INF/persistence.xml create mode 100644 src/it/dependency-test/h4mp/src/test/java/h4mp/MainEntityTest.java create mode 100644 src/it/dependency-test/h4mp/src/test/resources/META-INF/persistence.xml create mode 100644 src/it/dependency-test/pom.xml diff --git a/pom.xml b/pom.xml index df20ab05..6433f6f1 100644 --- a/pom.xml +++ b/pom.xml @@ -85,6 +85,10 @@ Mark Robinson mark@mrobinson.ca ++ Claus Graf +clausgraf@gmail.com +diff --git a/src/it/dependency-test/dependent/pom.xml b/src/it/dependency-test/dependent/pom.xml new file mode 100644 index 00000000..e7c15f39 --- /dev/null +++ b/src/it/dependency-test/dependent/pom.xml @@ -0,0 +1,26 @@ + + \ No newline at end of file diff --git a/src/it/dependency-test/dependent/src/main/java/dependent/DependentEntity.java b/src/it/dependency-test/dependent/src/main/java/dependent/DependentEntity.java new file mode 100644 index 00000000..16bc4044 --- /dev/null +++ b/src/it/dependency-test/dependent/src/main/java/dependent/DependentEntity.java @@ -0,0 +1,17 @@ +package dependent; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +import org.hibernate.envers.Audited; + +@Entity +@Audited +public class DependentEntity { + @Id + @GeneratedValue + long id; + + String name; +} diff --git a/src/it/dependency-test/h4mp/pom.xml b/src/it/dependency-test/h4mp/pom.xml new file mode 100644 index 00000000..4e179d25 --- /dev/null +++ b/src/it/dependency-test/h4mp/pom.xml @@ -0,0 +1,85 @@ +4.0.0 +de.cege +dependent +0.0.1 + ++ ++ +javax +javaee-api +7.0 +provided ++ +org.hibernate +hibernate-envers +4.3.5.Final ++ +1.7 +1.7 +false ++ diff --git a/src/it/dependency-test/h4mp/src/main/java/h4mp/MainEntity.java b/src/it/dependency-test/h4mp/src/main/java/h4mp/MainEntity.java new file mode 100644 index 00000000..f717d175 --- /dev/null +++ b/src/it/dependency-test/h4mp/src/main/java/h4mp/MainEntity.java @@ -0,0 +1,21 @@ +package h4mp; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.envers.Audited; + +import dependent.DependentEntity; + +@Entity +@Audited +public class MainEntity { + @Id + @GeneratedValue + long id; + + @ManyToOne + DependentEntity dependentEntity; +} diff --git a/src/it/dependency-test/h4mp/src/main/resources/META-INF/persistence.xml b/src/it/dependency-test/h4mp/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..a419eda9 --- /dev/null +++ b/src/it/dependency-test/h4mp/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,17 @@ + +4.0.0 +de.cege +h4mp +0.0.1-SNAPSHOT +war +h4mp + ++ ++ +javax +javaee-api +7.0 +provided ++ + +org.hibernate +hibernate-envers +4.3.5.Final ++ +junit +junit +4.8.2 +test ++ +org.apache.derby +derby +10.10.1.1 +test ++ +org.hibernate +hibernate-entitymanager +4.3.5.Final +test ++ + +org.slf4j +slf4j-simple +1.5.8 +test ++ +de.cege +dependent +0.0.1 ++ + +1.7 +1.7 +false ++ ++ ++ +de.juplo +hibernate4-maven-plugin +@project.version@ ++ ++ ++ +export ++ +NONE +true +true +; +true +CREATE +org.hibernate.dialect.PostgreSQL9Dialect ++ diff --git a/src/it/dependency-test/h4mp/src/test/java/h4mp/MainEntityTest.java b/src/it/dependency-test/h4mp/src/test/java/h4mp/MainEntityTest.java new file mode 100644 index 00000000..32e528fe --- /dev/null +++ b/src/it/dependency-test/h4mp/src/test/java/h4mp/MainEntityTest.java @@ -0,0 +1,49 @@ +package h4mp; + +import static org.junit.Assert.*; +import static org.hamcrest.core.Is.*; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import dependent.DependentEntity; + +public class MainEntityTest { + + private EntityManager em; + private EntityTransaction transaction; + + @Before + public void initializeDependencies() { + em = Persistence.createEntityManagerFactory("jpaIntegrationTest") + .createEntityManager(); + transaction = em.getTransaction(); + } + + @SuppressWarnings({ "rawtypes" }) + @Test + public void test() { + DependentEntity entity = new DependentEntity(); + + transaction.begin(); + em.persist(entity); + transaction.commit(); + + List resultList = em.createNativeQuery( + "select * from dependententity_aud").getResultList(); + assertThat(resultList.size(), is(1)); + } + + @After + public void after() { + em.close(); + } + +} diff --git a/src/it/dependency-test/h4mp/src/test/resources/META-INF/persistence.xml b/src/it/dependency-test/h4mp/src/test/resources/META-INF/persistence.xml new file mode 100644 index 00000000..83e13de6 --- /dev/null +++ b/src/it/dependency-test/h4mp/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,23 @@ ++ +java:jboss/datasources/PostgreSQLDS + +dependent.DependentEntity + ++ ++ + + + + diff --git a/src/it/dependency-test/pom.xml b/src/it/dependency-test/pom.xml new file mode 100644 index 00000000..8e1506ed --- /dev/null +++ b/src/it/dependency-test/pom.xml @@ -0,0 +1,13 @@ + ++ + +dependent.DependentEntity +h4mp.MainEntity + + ++ ++ + + + + + -- 2.20.1 From 426d18e689b89f33bf71601becfa465a00067b10 Mon Sep 17 00:00:00 2001 From: Kai Moritz4.0.0 +de.juplo +dependency-test +Hibernate 4 Dependency-Test +0.1-SNAPSHOT +pom ++ +dependent +h4mp +Date: Sat, 25 Oct 2014 17:29:41 +0200 Subject: [PATCH 08/16] Added patch by Joachim Van der Auwera to support package level annotations --- pom.xml | 4 + .../resources/spring-persistence-context.xml | 1 + src/it/schemaexport-example/schema.sql | 1 + .../schemaexport-example-domain/pom.xml | 4 + .../test/schemaexport/domain/Department.java | 4 + .../schemaexport/domain/EnumUserType.java | 110 ++++++ .../de/test/schemaexport/domain/Gender.java | 23 ++ .../schemaexport/domain/package-info.java | 13 + .../main/resources/META-INF/persistence.xml | 1 + .../juplo/plugins/hibernate4/Hbm2DdlMojo.java | 315 +++++++++--------- .../hibernate4/ValidationConfiguration.java | 5 + 11 files changed, 328 insertions(+), 153 deletions(-) create mode 100644 src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/EnumUserType.java create mode 100644 src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Gender.java create mode 100644 src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/package-info.java diff --git a/pom.xml b/pom.xml index 6433f6f1..272a1ea5 100644 --- a/pom.xml +++ b/pom.xml @@ -89,6 +89,10 @@ Claus Graf clausgraf@gmail.com ++ Joachim Van der Auwera +joachim@progs.be +diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml index 78f81117..0cff8cc6 100644 --- a/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml @@ -24,6 +24,7 @@ p:persistenceUnitName="${jpa.persistence.context.name}" p:persistenceXmlLocation="classpath:META-INF/persistence-jpa.xml" p:dataSource-ref="dataSource" + p:packagesToScan="de.test.schemaexport.domain" > diff --git a/src/it/schemaexport-example/schema.sql b/src/it/schemaexport-example/schema.sql index e8f93bae..bd7142cd 100644 --- a/src/it/schemaexport-example/schema.sql +++ b/src/it/schemaexport-example/schema.sql @@ -8,6 +8,7 @@ create table ABTEILUNG ( OID bigint generated by default as identity (start with 1), + gender varchar(255), name varchar(255) not null, primary key (OID) ); diff --git a/src/it/schemaexport-example/schemaexport-example-domain/pom.xml b/src/it/schemaexport-example/schemaexport-example-domain/pom.xml index c2bc2d8f..43b71b30 100644 --- a/src/it/schemaexport-example/schemaexport-example-domain/pom.xml +++ b/src/it/schemaexport-example/schemaexport-example-domain/pom.xml @@ -24,6 +24,10 @@ hibernate-validator provided ++ diff --git a/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Department.java b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Department.java index b523659c..64ff1332 100644 --- a/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Department.java +++ b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Department.java @@ -6,6 +6,7 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; +import org.hibernate.annotations.Type; /** * Abteilungsklasse (Generator-Beispielcode). @@ -25,6 +26,9 @@ public class Department { @Column(name = "name", nullable = false) private String name; + @Type(type = "genderType") + private Gender gender; + public long getOid() { return oid; } diff --git a/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/EnumUserType.java b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/EnumUserType.java new file mode 100644 index 00000000..6e598908 --- /dev/null +++ b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/EnumUserType.java @@ -0,0 +1,110 @@ +package de.test.schemaexport.domain; + +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.usertype.EnhancedUserType; +import org.hibernate.usertype.ParameterizedType; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Properties; + +/** + * This Hibernate UserType is used to map JDK 5 Enums directly in a column. + * Define this UserType in your hbm.xml mapping file like the following example: + */ +public class EnumUserType implements EnhancedUserType, ParameterizedType { + + private Classorg.hibernate +hibernate-core +enumClass; + + @Override + public void setParameterValues(Properties parameters) { + String enumClassName = parameters.getProperty("enumClassName"); + try { + enumClass = (Class ) Class.forName(enumClassName); + } catch (ClassNotFoundException cnfe) { + throw new HibernateException("Enum class not found", cnfe); + } + } + + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + @Override + public Object deepCopy(Object value) throws HibernateException { + return value; + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + return (Enum) value; + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + return x == y; + } + + @Override + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + @Override + public boolean isMutable() { + return false; + } + + @Override + public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor sessionImplementor, Object owner) + throws HibernateException, SQLException { + String name = rs.getString(names[0]); + return rs.wasNull() ? null : Enum.valueOf(enumClass, name); + } + + @Override + public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor sessionImplementor) + throws HibernateException, SQLException { + if (value == null) { + st.setNull(index, Types.VARCHAR); + } else { + st.setString(index, ((Enum) value).name()); + } + } + + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } + + @Override + public Class returnedClass() { + return enumClass; + } + + @Override + public int[] sqlTypes() { + return new int[]{Types.VARCHAR}; + } + + @Override + public Object fromXMLString(String xmlValue) { + return Enum.valueOf(enumClass, xmlValue); + } + + @Override + public String objectToSQLString(Object value) { + return '\'' + ((Enum) value).name() + '\''; + } + + @Override + public String toXMLString(Object value) { + return ((Enum) value).name(); + } + +} diff --git a/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Gender.java b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Gender.java new file mode 100644 index 00000000..dca1d000 --- /dev/null +++ b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/Gender.java @@ -0,0 +1,23 @@ +package de.test.schemaexport.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * Abteilungsklasse (Generator-Beispielcode). + * + * copyright + * + */ +public enum Gender { + + MALE, + FEMALE, + UNKNOWN, + OTHER + +} diff --git a/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/package-info.java b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/package-info.java new file mode 100644 index 00000000..d1491c6d --- /dev/null +++ b/src/it/schemaexport-example/schemaexport-example-domain/src/main/java/de/test/schemaexport/domain/package-info.java @@ -0,0 +1,13 @@ +@TypeDefs({ + @TypeDef(name = "genderType", + defaultForType = Gender.class, + typeClass = EnumUserType.class, + parameters = @Parameter(name = "enumClassName", + value = "de.test.schemaexport.domain.Gender")) +}) +package de.test.schemaexport.domain; + +import de.test.schemaexport.domain.EnumUserType; +import org.hibernate.annotations.Parameter; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; \ No newline at end of file diff --git a/src/it/schemaexport-example/schemaexport-example-persistence-impl/src/main/resources/META-INF/persistence.xml b/src/it/schemaexport-example/schemaexport-example-persistence-impl/src/main/resources/META-INF/persistence.xml index 75784726..0eaf2d3a 100644 --- a/src/it/schemaexport-example/schemaexport-example-persistence-impl/src/main/resources/META-INF/persistence.xml +++ b/src/it/schemaexport-example/schemaexport-example-persistence-impl/src/main/resources/META-INF/persistence.xml @@ -3,6 +3,7 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> + de.test.schemaexport.domain de.test.schemaexport.domain.Department de.test.schemaexport.domain.Employee diff --git a/src/main/java/de/juplo/plugins/hibernate4/Hbm2DdlMojo.java b/src/main/java/de/juplo/plugins/hibernate4/Hbm2DdlMojo.java index f73fa2b5..73f0ab06 100644 --- a/src/main/java/de/juplo/plugins/hibernate4/Hbm2DdlMojo.java +++ b/src/main/java/de/juplo/plugins/hibernate4/Hbm2DdlMojo.java @@ -58,7 +58,6 @@ import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; -import org.hibernate.cfg.Configuration; import org.hibernate.cfg.NamingStrategy; import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.tool.hbm2ddl.SchemaExport; @@ -670,7 +669,7 @@ public class Hbm2DdlMojo extends AbstractMojo throw new MojoFailureException("Hibernate configuration is missing!"); } - final Configuration config = new ValidationConfiguration(hibernateDialect); + final ValidationConfiguration config = new ValidationConfiguration(hibernateDialect); config.setProperties(properties); @@ -691,181 +690,191 @@ public class Hbm2DdlMojo extends AbstractMojo } } - getLog().debug("Adding annotated classes to hibernate-mapping-configuration..."); - for (Class> annotatedClass : classes) + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + Connection connection = null; + MavenLogAppender.startPluginLog(this); + try { - getLog().debug("Class " + annotatedClass); - config.addAnnotatedClass(annotatedClass); - } + /** + * Change class-loader of current thread, so that hibernate can + * see all dependencies! + */ + Thread.currentThread().setContextClassLoader(classLoader); - if (hibernateMapping != null) - { - try + getLog().debug("Adding annotated classes to hibernate-mapping-configuration..."); + // build annotated packages + Set packages = new HashSet (); + for (Class> annotatedClass : classes) { - MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); - for (String filename : hibernateMapping.split("[\\s,]+")) + String packageName = annotatedClass.getPackage().getName(); + if (!packages.contains(packageName)) { - // First try the filename as absolute/relative path - File file = new File(filename); - if (!file.exists()) + getLog().debug("Add package " + packageName); + packages.add(packageName); + config.addPackage(packageName); + getLog().debug("type definintions" + config.getTypeDefs()); + } + getLog().debug("Class " + annotatedClass); + config.addAnnotatedClass(annotatedClass); + } + + if (hibernateMapping != null) + { + try + { + MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); + for (String filename : hibernateMapping.split("[\\s,]+")) { - // If the file was not found, search for it in the resource-directories - for (Resource resource : project.getResources()) + // First try the filename as absolute/relative path + File file = new File(filename); + if (!file.exists()) { - file = new File(resource.getDirectory() + File.separator + filename); - if (file.exists()) - break; + // If the file was not found, search for it in the resource-directories + for (Resource resource : project.getResources()) + { + file = new File(resource.getDirectory() + File.separator + filename); + if (file.exists()) + break; + } } - } - if (file != null && file.exists()) - { - InputStream is = new FileInputStream(file); - byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks - int i; - while((i = is.read(buffer)) > -1) - digest.update(buffer, 0, i); - is.close(); - byte[] bytes = digest.digest(); - BigInteger bi = new BigInteger(1, bytes); - String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi); - String oldMd5 = !md5s.containsKey(filename) ? "" : md5s.get(filename); - if (!newMd5.equals(oldMd5)) + if (file != null && file.exists()) { - getLog().debug("Found new or modified mapping-file: " + filename); - modified = true; - md5s.put(filename, newMd5); + InputStream is = new FileInputStream(file); + byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks + int i; + while((i = is.read(buffer)) > -1) + digest.update(buffer, 0, i); + is.close(); + byte[] bytes = digest.digest(); + BigInteger bi = new BigInteger(1, bytes); + String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi); + String oldMd5 = !md5s.containsKey(filename) ? "" : md5s.get(filename); + if (!newMd5.equals(oldMd5)) + { + getLog().debug("Found new or modified mapping-file: " + filename); + modified = true; + md5s.put(filename, newMd5); + } + else + { + getLog().debug(oldMd5 + " -> mapping-file unchanged: " + filename); + } + getLog().debug("Adding mappings from XML-configurationfile: " + file); + config.addFile(file); } else - { - getLog().debug(oldMd5 + " -> mapping-file unchanged: " + filename); - } - getLog().debug("Adding mappings from XML-configurationfile: " + file); - config.addFile(file); + throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!"); } - else - throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!"); + } + catch (NoSuchAlgorithmException e) + { + throw new MojoFailureException("Cannot calculate MD5 sums!", e); + } + catch (FileNotFoundException e) + { + throw new MojoFailureException("Cannot calculate MD5 sums!", e); + } + catch (IOException e) + { + throw new MojoFailureException("Cannot calculate MD5 sums!", e); } } - catch (NoSuchAlgorithmException e) + + Target target = null; + try { - throw new MojoFailureException("Cannot calculate MD5 sums!", e); + target = Target.valueOf(this.target.toUpperCase()); } - catch (FileNotFoundException e) + catch (IllegalArgumentException e) { - throw new MojoFailureException("Cannot calculate MD5 sums!", e); + getLog().error("Invalid value for configuration-option \"target\": " + this.target); + getLog().error("Valid values are: NONE, SCRIPT, EXPORT, BOTH"); + throw new MojoExecutionException("Invalid value for configuration-option \"target\""); } - catch (IOException e) + Type type = null; + try { - throw new MojoFailureException("Cannot calculate MD5 sums!", e); + type = Type.valueOf(this.type.toUpperCase()); + } + catch (IllegalArgumentException e) + { + getLog().error("Invalid value for configuration-option \"type\": " + this.type); + getLog().error("Valid values are: NONE, CREATE, DROP, BOTH"); + throw new MojoExecutionException("Invalid value for configuration-option \"type\""); } - } - - Target target = null; - try - { - target = Target.valueOf(this.target.toUpperCase()); - } - catch (IllegalArgumentException e) - { - getLog().error("Invalid value for configuration-option \"target\": " + this.target); - getLog().error("Valid values are: NONE, SCRIPT, EXPORT, BOTH"); - throw new MojoExecutionException("Invalid value for configuration-option \"target\""); - } - Type type = null; - try - { - type = Type.valueOf(this.type.toUpperCase()); - } - catch (IllegalArgumentException e) - { - getLog().error("Invalid value for configuration-option \"type\": " + this.type); - getLog().error("Valid values are: NONE, CREATE, DROP, BOTH"); - throw new MojoExecutionException("Invalid value for configuration-option \"type\""); - } - if (target.equals(Target.SCRIPT) || target.equals(Target.NONE)) - { - project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); - } - if ( - !modified - && !target.equals(Target.SCRIPT) - && !target.equals(Target.NONE) - && !force - ) - { - getLog().info("No modified annotated classes or mapping-files found and dialect unchanged."); - getLog().info("Skipping schema generation!"); - project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); - return; - } + if (target.equals(Target.SCRIPT) || target.equals(Target.NONE)) + { + project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); + } + if ( + !modified + && !target.equals(Target.SCRIPT) + && !target.equals(Target.NONE) + && !force + ) + { + getLog().info("No modified annotated classes or mapping-files found and dialect unchanged."); + getLog().info("Skipping schema generation!"); + project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); + return; + } - getLog().info("Gathered hibernate-configuration (turn on debugging for details):"); - for (Entry ->plugin< +<plugin> <groupId>de.juplo</groupId> <artifactId>hibernate4-maven-plugin</artifactId> ... @@ -163,5 +163,21 @@ mvn hibernate4:export -Dhibernate.export.force=trueBackground-information for this design-decission can be found on the extra page To skip or not to skip: that is the question... +I do not want my dependencies to be scanned for hibernate annotations
++ If you do not want your dependencies to be scanned for hibernate annotations, + you can pass
+-Dhibernate.export.scan_dependencies=none
to maven + or setscanDependencies
tonone
in the configuration + of the plugin like this: ++<plugin> + <groupId>de.juplo</groupId> + <artifactId>hibernate4-maven-plugin</artifactId> + ... + <configuration> + <scanDependencies>none</scanDependencies> + </configuration> +</plugin>