Nauka Java Persistence z Apache Maven 2 i dostawcami JPA: OpenJPA, Hibernate i TopLink
Z Jacek Laskowski - Wiki Projektanta Java EE
Mając zestawione środowisko do nauki Java Persistence API (JPA), które przedstawiłem w artykule Java Persistence API z OpenJPA i Derby oraz TestNG z Eclipse IDE w tle postanowiłem je ulepszyć. Celem zmian było wprowadzenie możliwości weryfikacji implementacji specyfikacji JPA wśród różnych dostawców JPA - Apache OpenJPA, Hibernate EntityManager oraz TopLink Essentials. Oczywiście lista dostawców JPA może ulec zmianie w razie potrzeby. Możliwość uruchomienia testów jednostkowych napisanych w TestNG z różnymi dostawcami była możliwa dzięki wykorzystaniu Apache Maven 2, a dokładniej mechanizmowi profili. Wystarczyło odpowiednio zdefiniować profil w pliku projektu - pom.xml i reszta pozostała w gestii Apache Maven 2 (dalej zwanym M2).
Spis treści |
Zanim zaczniemy...
Ważne jest, aby rozpocząć artykuł od zestawienia środowiska do uruchamiania testów TestNG z Apache Maven 2, gdzie dostawcą JPA jest Apache OpenJPA zgodnie z artykułem Java Persistence API z OpenJPA i Derby oraz TestNG z Eclipse IDE w tle.
Krótko o profilach w Apache Maven 2
Możliwość uruchamiania testów z różnymi dostawcami JPA jest możliwa korzystając z mechanizmu profili w Apache Maven 2. Profil pozwala na podział konfiguracji projektu - pom.xml - na mniejsze jednostki uzależnione od pewnych ustawień środowiska, które modyfikują główną konfigurację projektu (powodują, że wykonanie zadań w projekcie odbywa się jakby ustawienia profili były podstawowymi w projekcie z elementami konfiguracji głównej). W ten sposób możemy grupować konfiguracje w pojedyńczym projekcie i wyzwalać je jakby były one podstawowymi ustawieniami.
Wykonanie profilu odbywa się przy pomocy opcji -P<nazwa_profilu>. Istnieje również możliwość wykonania profilu w inny sposób, np. zmienna środowiskowa, czy wersja Javy, który jest zdefiniowany w elemencie <activation> profilu. Skorzystamy z możliwości definicji domyślnego profilu przy OpenJPA.
Domyślny profil projektu - openjpa
Mając zdefiniowane środowisko testowe z OpenJPA (patrz poprzedni artykuł), wprowadzamy nowy profil - openjpa - do projektu. Funkcjonalnie, zmiana nie wpłynie w żaden sposób na dotychczasową konfigurację, jednakże dzięki niemu przygotujemy grunt pod kolejne. Profil openjpa będzie profilem domyślnie uruchamianym.
Plik pom.xml
Modyfikujemy plik pom.xml projektu, aby przybrał następującą postać:
<?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>pl.jaceklaskowski.jpa.query</groupId> <artifactId>jpa-query</artifactId> <name>jpa-query</name> <version>1.0</version> <dependencies> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>10.2.2.0</version> </dependency> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derbyclient</artifactId> <version>10.2.2.0</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>5.1</version> <scope>test</scope> <classifier>jdk15</classifier> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration>
Niepoprawny język.
Musisz wybrać język w następujący sposób: <source lang="html4strict">...</source>
Języki obsługiwane w podświetlaniu składni:
abap, actionscript, actionscript3, ada, apache, applescript, apt_sources, asm, asp, autoit, avisynth, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_mac, caddcl, cadlisp, cfdg, cfm, cil, cmake, cobol, cpp, cpp-qt, csharp, css, d, dcs, delphi, diff, div, dos, dot, eiffel, email, erlang, fo, fortran, freebasic, genero, gettext, glsl, gml, gnuplot, groovy, haskell, hq9plus, html4strict, idl, ini, inno, intercal, io, java, java5, javascript, kixtart, klonec, klonecpp, latex, lisp, locobasic, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, make, matlab, mirc, modula3, mpasm, mxml, mysql, nsis, oberon2, objc, ocaml, ocaml-brief, oobas, oracle11, oracle8, pascal, per, perl, php, php-brief, pic16, pixelbender, plsql, povray, powershell, progress, prolog, properties, providex, python, qbasic, rails, rebol, reg, robots, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, tcl, teraterm, text, thinbasic, tsql, typoscript, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xml, xorg_conf, xpp, z80
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>openjpa</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>0.9.7-incubating-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>enhance</goal>
</goals>
<configuration>
<toolProperties>
<property>
<name>addDefaultConstructor</name>
<value>true</value>
</property>
<property>
<name>enforcePropertyRestrictions</name>
<value>true</value>
</property>
</toolProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources/openjpa</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
</project>
Katalog plików pomocniczych - src/main/resources/openjpa
Jednym z istotnych elementów w nowej konfiguracji jest inna organizacja katalogu z plikami pomocnicznymi projektu. Każdy dostawca JPA posiada własną konfigurację i każdy otrzyma swój własny katalog na pliki konfiguracyjne, m.in. META-INF/persistence.xml (można pokusić się o sprytniejszą konfigurację, ale pozostawiam to dociekliwym jako zadanie domowe).
Tworzymy nowy katalog src/main/resources/openjpa, w którym umieszczamy katalog META-INF z plikiem persistence.xml.
Konfiguracja dostawcy JPA oraz jednostki utrwalania - META-INF/persistence.xml
Zawartość pliku persistence.xml dla Apache OpenJPA jako dostawcy JPA z wbudowaną bazą danych Apache Derby przedstawia się następująco:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" 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_1_0.xsd"> <persistence-unit name="derbyPU" transaction-type="RESOURCE_LOCAL"> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <class>pl.jaceklaskowski.jpa.entity.Osoba</class> <class>pl.jaceklaskowski.jpa.entity.Projekt</class> <class>pl.jaceklaskowski.jpa.entity.PracownikSpecjalny</class> <exclude-unlisted-classes /> <properties> <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.EmbeddedDriver" /> <property name="openjpa.ConnectionURL" value="jdbc:derby:target/derbyDB;create=true" /> <property name="openjpa.ConnectionUserName" value="app" /> <property name="openjpa.ConnectionPassword" value="app" /> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction='add,deleteTableContents')" /> <property name="openjpa.Log" value="DefaultLevel=TRACE,SQL=TRACE" /> </properties> </persistence-unit> </persistence>
Uruchomienie
Mając tak zdefiniowany projekt wykonanie testów pozostaje bez zmian, np. mvn clean test (ze względu na element activeByDefault o wartości true), bądź analogicznie, z jawnym wskazaniem profilu, mvn -Popenjpa clean test.
Na uwagę zasługuje również możliwość uruchomienia pojedyńczego testu przy pomocy -Dtest=<nazwa_skrócona_klasy_testu>, np. mvn -Dtest=ConditionalExpressionsTest -Popenjpa clean test (oczywiście -Popenjpa jest opcjonalne).
$ mvn -Dtest=ConditionalExpressionsTest -Popenjpa clean test
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building jpa-query
[INFO] task-segment: [clean, test]
[INFO] ----------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory c:\projs\jpa\target
[INFO] Deleting directory c:\projs\jpa\target\classes
[INFO] Deleting directory c:\projs\jpa\target\test-classes
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 5 source files to c:\projs\jpa\target\classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [openjpa:enhance {execution: default}]
[INFO]
[ERROR] --------------------
[ERROR] Standard error from the OpenJPA Enhancer tool:
[ERROR] --------------------
[ERROR] 0 derbyPU TRACE [main] openjpa.Runtime - Setting the following properties from "file:/C:/projs/jpa/target/classes/META-INF/persistence.xml" into configuration: {openjpa.
jdbc.SynchronizeMappings=buildSchema(SchemaAction='add,deleteTableContents'), openjpa.ConnectionUserName=app, openjpa.ConnectionPassword=app, openjpa.Log=DefaultLevel=TRACE,SQL=TRA
CE, openjpa.MetaDataFactory=jpa(Types=pl.jaceklaskowski.jpa.entity.Osoba;pl.jaceklaskowski.jpa.entity.Projekt;pl.jaceklaskowski.jpa.entity.PracownikSpecjalny), javax.persistence.pr
ovider=org.apache.openjpa.persistence.PersistenceProviderImpl, openjpa.ConnectionURL=jdbc:derby:target/derbyDB;create=true, openjpa.ConnectionDriverName=org.apache.derby.jdbc.Embed
dedDriver, openjpa.Id=derbyPU}
78 derbyPU INFO [main] openjpa.Tool - Enhancer running on type "class pl.jaceklaskowski.jpa.entity.Osoba".
141 derbyPU TRACE [main] openjpa.MetaData - Loading metadata for "class pl.jaceklaskowski.jpa.entity.Osoba" under mode "[META]".
141 derbyPU TRACE [main] openjpa.MetaData - Scanning resource "META-INF/orm.xml" for persistent types.
156 derbyPU TRACE [main] openjpa.MetaData - parsePersistentTypeNames() found [pl.jaceklaskowski.jpa.entity.PracownikSpecjalny, pl.jaceklaskowski.jpa.entity.Osoba, pl.jaceklaskow
ski.jpa.entity.Projekt].
156 derbyPU INFO [main] openjpa.MetaData - Found 3 classes with metadata in 15 milliseconds.
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running pl.jaceklaskowski.jpa.chapter4_6.ConditionalExpressionsTest
15 derbyPU TRACE [main] openjpa.Runtime - Setting the following properties from "file:/c:/projs/jpa/target/classes/META-INF/persistence.xml" into configuration: {openjpa.jdbc.Sy
nchronizeMappings=buildSchema(SchemaAction='add,deleteTableContents'), openjpa.BrokerFactory=jdbc, openjpa.ConnectionUserName=app, openjpa.ConnectionPassword=app, openjpa.Log=Defau
ltLevel=TRACE,SQL=TRACE, openjpa.MetaDataFactory=jpa(Types=pl.jaceklaskowski.jpa.entity.Osoba;pl.jaceklaskowski.jpa.entity.Projekt;pl.jaceklaskowski.jpa.entity.PracownikSpecjalny),
javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl, openjpa.ConnectionURL=jdbc:derby:target/derbyDB;create=true, openjpa.ConnectionDriverName=org.ap
ache.derby.jdbc.EmbeddedDriver, openjpa.Id=derbyPU}
62 derbyPU INFO [main] openjpa.Runtime - Starting OpenJPA 0.9.7-incubating-SNAPSHOT
...
3515 derbyPU TRACE [main] openjpa.Query - Executing query: SELECT DISTINCT o FROM Osoba o, IN(o.projekty) p WHERE p.rodzajProjektu = pl.jaceklaskowski.jpa.entity.RodzajProjektu.
OTWARTY
3609 derbyPU TRACE [main] openjpa.jdbc.SQL - <t 9971081, conn 27585366> executing prepstmnt 33066941 SELECT DISTINCT t0.numer, t0.dzienImienin, t0.dzienUrodzin, t0.imie, t0.kraj
, t0.nazwisko, t0.tytul FROM Osoba t0 INNER JOIN Osoba_Projekt t1 ON t0.numer = t1.Osoba_numer INNER JOIN Projekt t2 ON t1.projekty_nazwa = t2.nazwa WHERE (t2.rodzajProjektu = ?) [
params=(int) 0]
3609 derbyPU TRACE [main] openjpa.jdbc.SQL - <t 9971081, conn 27585366> [0 ms] spent
3609 derbyPU TRACE [main] openjpa.jdbc.JDBC - <t 9971081, conn 27585366> [0 ms] close
3968 derbyPU TRACE [main] openjpa.MetaData - Clearing metadata repository "org.apache.openjpa.jdbc.meta.MappingRepository@c12978".
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.344 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9 seconds
[INFO] Finished at: Tue Mar 27 00:10:46 CEST 2007
[INFO] Final Memory: 7M/254M
[INFO] ------------------------------------------------------------------------
Na uwagę zasługuje wyświetlenie wersji wykorzystywanego oprogramowania - OpenJPA 0.9.7-incubating-SNAPSHOT, co ma niebagatelne znaczenie podczas rozwiązywania ewentualnych problemów.
Profil projektu - hibernate
Instalacja zależności w lokalnym repozytorium Apache Maven 2
Kolejny profil - hibernate - posłuży nam do uruchamiania testów korzystając z Hibernate EntityManager (Hibernate JPA).
W przypadku nauki specyfikacji Java Persistence zalecane jest, abyśmy korzystali z najświeższych wersji oprogramowania, które zapewni nam kompletne środowisko JPA z możliwie niewielką ilością błędów i niezgodności. Do uruchomienia Hibernate w roli dostawcy JPA będą nam potrzebne następujące wersje projektów:
- Hibernate Core 3.2.2 GA
- Hibernate Annotations 3.3.0 GA
- Hibernate EntityManager 3.3.0 GA
- Hibernate Validator 3.0.0 GA
Wszystkie są do pobrania na stronie Hibernate Binary Releases.
Konieczne jest ich pobranie, ponieważ wymienione wersje nie są dostępne w żadnym ze znanych repozytoriów M2 i będziemy musieli zainstalować je w lokalnym repozytorium ręcznie.
Po rozpakowaniu wspomnianych bibliotek instalujemy je i ich zależności do lokalnego repozytorium:
mvn install:install-file -DgroupId=org.hibernate -DartifactId=hibernate-annotations \ -Dversion=3.3.0.ga -Dpackaging=jar -Dfile=c:/apps/hibernate-annotations-3.3.0.GA/hibernate-annotations.jar mvn install:install-file -DgroupId=org.hibernate -DartifactId=hibernate-entitymanager \ -Dversion=3.3.0.ga -Dpackaging=jar -Dfile=c:/apps/hibernate-entitymanager-3.3.0.GA/hibernate-entitymanager.jar mvn install:install-file -DgroupId=org.hibernate -DartifactId=hibernate-commons-annotations \ -Dversion=3.0.0.GA -Dpackaging=jar -Dfile=c:/apps/hibernate-entitymanager-3.3.0.GA/lib/hibernate-commons-annotations.jar mvn install:install-file -DgroupId=org.hibernate -DartifactId=hibernate-validator \ -Dversion=3.0.0.ga -Dpackaging=jar -Dfile=c:/apps/hibernate-validator-3.0.0.GA/hibernate-validator.jar mvn install:install-file -DgroupId=javassist -DartifactId=javassist \ -Dversion=3.4 -Dpackaging=jar -Dfile=c:/apps/hibernate-3.2.2.GA/lib/javassist.jar
Dodatkowo potrzebna będzie biblioteka JTA 1.0.1B, który nie znajduje się w repozytoriach M2 ze względu na jej licencję (więcej na stronie Coping with SUN JARs), ale jest dystrybuowana m.in. z Hibernate, więc wystarczy zainstalować bibliotekę do repozytorium lokalnego Maven wykonując polecenie:
mvn install:install-file -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dpackaging=jar -Dfile=c:/apps/hibernate-3.2.2.GA/lib/jta.jar
Plik pom.xml
Po zainstalowaniu bibliotek w lokalnym repozytorium Maven, przechodzimy do konfiguracji projektu - modyfikacji pliku pom.xml - o definicję profilu hibernate.
Część pliku pom.xml odpowiadająca profilowi hibernate:
<profile>
<id>hibernate</id>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.2.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.0.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.0.0.GA</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-archive-browsing</artifactId>
<version>5.0.0alpha-200607201-119</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources/hibernate</directory>
</resource>
</resources>
</build>
</profile>
Katalog plików pomocniczych - src/main/resources/hibernate
Tworzymy katalog src/main/resources/hibernate
Konfiguracja dostawcy JPA oraz jednostki utrwalania - META-INF/persistence.xml
Katalog src/main/resources/hibernate zawiera plik META-INF/persistence.xml (obok już istniejącego katalogu z konfiguracją openjpa):
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" 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_1_0.xsd"> <persistence-unit name="derbyPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>pl.jaceklaskowski.jpa.entity.Osoba</class> <class>pl.jaceklaskowski.jpa.entity.Projekt</class> <class>pl.jaceklaskowski.jpa.entity.PracownikSpecjalny</class> <exclude-unlisted-classes /> <properties> <property name="hibernate.archive.autodetection" value="class, hbm" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver" /> <property name="hibernate.connection.url" value="jdbc:derby:target/derbyDB;create=true" /> <property name="hibernate.connection.username" value="app" /> <property name="hibernate.connection.password" value="app" /> <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" /> <property name="hibernate.hbm2ddl.auto" value="create-drop" /> </properties> </persistence-unit> </persistence>
Uruchomienie
Wykonanie testów z Hibernate jako dostawcą JPA i wbudowaną bazą danych Apache Derby, lub innymi słowy uruchomienie profilu hibernate, sprowadza się do wywołania polecenia mvn -Phibernate clean test. W przypadku profilu hibernate, jedyną możliwością jego uruchomienia jest jawne podanie jego nazwy jako argument opcji -P.
$ mvn -Dtest=ConditionalExpressionsTest -Phibernate clean test
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building jpa-query
[INFO] task-segment: [clean, test]
[INFO] ----------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory c:\projs\jpa\target
[INFO] Deleting directory c:\projs\jpa\target\classes
[INFO] Deleting directory c:\projs\jpa\target\test-classes
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running pl.jaceklaskowski.jpa.chapter4_6.ConditionalExpressionsTest
2007-03-27 00:15:40 org.hibernate.cfg.annotations.Version <clinit>
INFO: Hibernate Annotations 3.3.0.GA
2007-03-27 00:15:40 org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.2.2
2007-03-27 00:15:40 org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
2007-03-27 00:15:40 org.hibernate.cfg.Environment buildBytecodeProvider
INFO: Bytecode provider name : cglib
2007-03-27 00:15:40 org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
2007-03-27 00:15:40 org.hibernate.ejb.Version <clinit>
INFO: Hibernate EntityManager 3.3.0.GA
2007-03-27 00:15:40 org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: pl.jaceklaskowski.jpa.entity.Osoba
2007-03-27 00:15:40 org.hibernate.cfg.annotations.QueryBinder bindQuery
INFO: Binding Named query: wszystkieOsoby => SELECT o FROM Osoba o
2007-03-27 00:15:40 org.hibernate.cfg.annotations.QueryBinder bindQuery
INFO: Binding Named query: znajdzOsobyPoImieniu => SELECT o FROM Osoba o WHERE o.imie LIKE :imie
2007-03-27 00:15:40 org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity pl.jaceklaskowski.jpa.entity.Osoba on table Osoba
2007-03-27 00:15:40 org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: pl.jaceklaskowski.jpa.entity.Projekt
2007-03-27 00:15:40 org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity pl.jaceklaskowski.jpa.entity.Projekt on table Projekt
2007-03-27 00:15:40 org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: pl.jaceklaskowski.jpa.entity.PracownikSpecjalny
2007-03-27 00:15:40 org.hibernate.validator.Version <clinit>
INFO: Hibernate Validator 3.0.0.GA
2007-03-27 00:15:41 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
2007-03-27 00:15:41 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 20
2007-03-27 00:15:41 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: true
2007-03-27 00:15:41 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.apache.derby.jdbc.EmbeddedDriver at URL: jdbc:derby:target/derbyDB;create=true
2007-03-27 00:15:41 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=app, password=****, autocommit=true, release_mode=auto}
2007-03-27 00:15:42 org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: Apache Derby, version: 10.2.2.0 - (485682)
2007-03-27 00:15:42 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: Apache Derby Embedded JDBC Driver, version: 10.2.2.0 - (485682)
2007-03-27 00:15:42 org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.DerbyDialect
...
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.343 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8 seconds
[INFO] Finished at: Tue Mar 27 00:15:44 CEST 2007
[INFO] Final Memory: 6M/254M
[INFO] ------------------------------------------------------------------------
I kolejny raz możemy przekonać się o wykorzystywanym oprogramowaniu - Hibernate Annotations 3.3.0.GA, Hibernate EntityManager 3.3.0.GA, Hibernate Validator 3.0.0.GA, Apache Derby, version: 10.2.2.0 - (485682), Apache Derby Embedded JDBC Driver, version: 10.2.2.0 - (485682).
Profil projektu - toplink
Plik pom.xml
Kolejny profil - toplink - to powtórzenie kroków wykonywanych poprzednio z profilami openjpa oraz hibernate (za wyjątkiem instalacji zależności w lokalnym repozytorium). Modyfikacja pliku pom.xml sprowadza się do dodania następującej sekcji:
<profile>
<id>toplink</id>
<dependencies>
<dependency>
<groupId>toplink.essentials</groupId>
<artifactId>toplink-essentials</artifactId>
<version>2.0-40</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources/toplink</directory>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>java.net</id>
<name>java.net Maven Repository</name>
<url>https://maven-repository.dev.java.net/nonav/repository</url>
<layout>legacy</layout>
</repository>
</repositories>
</profile>
Ważnym elementem jest definicja nowego repozytorium Maven - java.net - dla zależności toplink.essentials.toplink-essentials-2.0-40.jar. Jest to repozytorium, w którym znajduje się wiele bibliotek będących implementacjami specyfikacji Java EE 5.
Katalog plików pomocniczych - src/main/resources/toplink
Tworzymy dedykowany katalog src/main/resources/toplink.
Konfiguracja dostawcy JPA oraz jednostki utrwalania - META-INF/persistence.xml
Katalog src/main/resources/toplink zawiera plik META-INF/persistence.xml (obok już istniejących katalogów z konfiguracją openjpa i hibernate):
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" 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_1_0.xsd"> <persistence-unit name="derbyPU" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider> <class>pl.jaceklaskowski.jpa.entity.Osoba</class> <class>pl.jaceklaskowski.jpa.entity.Projekt</class> <class>pl.jaceklaskowski.jpa.entity.PracownikSpecjalny</class> <exclude-unlisted-classes /> <properties> <property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" /> <property name="toplink.jdbc.url" value="jdbc:derby:target/derbyDB;create=true" /> <property name="toplink.jdbc.user" value="app" /> <property name="toplink.jdbc.password" value="app" /> <property name="toplink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> </persistence>
Uruchomienie
Wykonanie testów z TopLink Essentials jako dostawcą JPA, lub innymi słowy uruchomienie profilu toplink, sprowadza się do wywołania polecenia mvn -Ptoplink clean test. Podobnie jak miało to miejsce w przypadku profilu hibernate konieczne jest podanie opcji -P z wartością toplink.
$ mvn -Dtest=ConditionalExpressionsTest -Ptoplink clean test [INFO] Scanning for projects... [INFO] ---------------------------------------------------------------------------- [INFO] Building jpa-query [INFO] task-segment: [clean, test] [INFO] ---------------------------------------------------------------------------- [INFO] [clean:clean] [INFO] Deleting directory c:\projs\jpa\target [INFO] Deleting directory c:\projs\jpa\target\classes [INFO] Deleting directory c:\projs\jpa\target\test-classes [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Compiling 5 source files to c:\projs\jpa\target\classes [INFO] [resources:testResources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:testCompile] [INFO] Compiling 4 source files to c:\projs\jpa\target\test-classes [INFO] [surefire:test] [INFO] Surefire report directory: c:\projs\jpa\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running pl.jaceklaskowski.jpa.chapter4_6.ConditionalExpressionsTest [TopLink Info]: 2007.03.27 12:06:09.843--ServerSession(3794357)--TopLink, version: Oracle TopLink Essentials - 2.0 (Build 40 (03/21/2007)) [TopLink Info]: 2007.03.27 12:06:11.812--ServerSession(3794357)--file:/c:/projs/jpa/target/classes/-derbyPU login successful [TopLink Info]: 2007.03.27 12:06:12.765--ServerSession(3794357)--file:/c:/projs/jpa/target/classes/-derbyPU logout successful Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.063 sec Results : Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 7 seconds [INFO] Finished at: Tue Mar 27 00:06:12 CEST 2007 [INFO] Final Memory: 5M/254M [INFO] ------------------------------------------------------------------------
Na uwagę zasługuje wyświetlenie wersji TopLink Essentials 2.0 Build 40.
Kompletna konfiguracja projektu - pom.xml
Kompletny plik pom.xml z profilami openjpa, hibernate oraz toplink przedstawia się następująco:
<?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>pl.jaceklaskowski.jpa.query</groupId> <artifactId>jpa-query</artifactId> <name>jpa-query</name> <version>1.0</version> <dependencies> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>10.2.2.0</version> </dependency> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derbyclient</artifactId> <version>10.2.2.0</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>5.1</version> <scope>test</scope> <classifier>jdk15</classifier> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration>
Niepoprawny język.
Musisz wybrać język w następujący sposób: <source lang="html4strict">...</source>
Języki obsługiwane w podświetlaniu składni:
abap, actionscript, actionscript3, ada, apache, applescript, apt_sources, asm, asp, autoit, avisynth, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_mac, caddcl, cadlisp, cfdg, cfm, cil, cmake, cobol, cpp, cpp-qt, csharp, css, d, dcs, delphi, diff, div, dos, dot, eiffel, email, erlang, fo, fortran, freebasic, genero, gettext, glsl, gml, gnuplot, groovy, haskell, hq9plus, html4strict, idl, ini, inno, intercal, io, java, java5, javascript, kixtart, klonec, klonecpp, latex, lisp, locobasic, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, make, matlab, mirc, modula3, mpasm, mxml, mysql, nsis, oberon2, objc, ocaml, ocaml-brief, oobas, oracle11, oracle8, pascal, per, perl, php, php-brief, pic16, pixelbender, plsql, povray, powershell, progress, prolog, properties, providex, python, qbasic, rails, rebol, reg, robots, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, tcl, teraterm, text, thinbasic, tsql, typoscript, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xml, xorg_conf, xpp, z80
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>openjpa</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>0.9.7-incubating-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>enhance</goal>
</goals>
<configuration>
<toolProperties>
<property>
<name>addDefaultConstructor</name>
<value>true</value>
</property>
<property>
<name>enforcePropertyRestrictions</name>
<value>true</value>
</property>
</toolProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources/openjpa</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>hibernate</id>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.2.ga</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-archive-browsing</artifactId>
<version>5.0.0alpha-200607201-119</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.0.0.ga</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.0.1B</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.0.0.GA</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources/hibernate</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>toplink</id>
<dependencies>
<dependency>
<groupId>toplink.essentials</groupId>
<artifactId>toplink-essentials</artifactId>
<version>2.0-40</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources/toplink</directory>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>java.net</id>
<name>java.net Maven Repository</name>
<url>https://maven-repository.dev.java.net/nonav/repository</url>
<layout>legacy</layout>
</repository>
</repositories>
</profile>
</profiles>
</project>
Eclipse IDE a profile Maven 2
Podczas modyfikacji projektu zdefiniowaliśmy openjpa jako domyślny profil projektu. Eclipse nie rozpoznaje profili i koniecznie należy zdefiniować pojedyńczy katalog zawierający META-INF/persistence.xml, aby był katalogiem ze źródłami. W ten sposób nadal będziemy mieli możliwość uruchamiania testów z wybranym dostawcą JPA, np. Apache OpenJPA, z poziomu Eclipse IDE.




