8. Spring Data JPA OpenJpa
8.1. Introduction
We nemen de vorige architectuur over, die we nu implementeren met een JPA / OpenJpa-laag.
![]() |
8.2. Het opzetten van de werkomgeving
Download met STS het project [myql-config-jpa-eclipselink] [1-4]:
![]() |
en importeer vervolgens het project [mysl-config-jpa-openjpa] [5] dat zich in de map [<exemples>/spring-database-config/mysql/eclipse] [6] bevindt:
![]() |
Zodra dit is gebeurd, reset je de Maven-omgeving (Alt-F5) van alle projecten in [Package Explorer]:
![]() |
Voer vervolgens, om de werkomgeving te controleren, de uitvoerconfiguratie met de naam [spring-jpa-generic-JUnitTestDao-openjpa] uit:
![]() | ![]() |
Deze configuratie voert de test [JUnitTestDao] uit. Deze test moet slagen:
![]() |
8.3. Het configuratieproject van de laag JPA
![]() |
Dit project heeft als doel de laag JPA van de onderstaande architectuur te configureren:
![]() |
8.3.1. Maven-configuratie
Het project is een Maven-project en wordt geconfigureerd door het volgende bestand [pom.xml]:
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>dvp.spring.database</groupId>
<artifactId>generic-config-jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>configuration mysql openjpa</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
</parent>
<dependencies>
<!-- variabele afhankelijkheden ********************************************** -->
<!-- JPA-provider -->
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<version>2.3.0</version>
</dependency>
<!-- constante afhankelijkheden ********************************************** -->
<!-- Spring Data -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<!-- overgenomen configuratie van JDBC -->
<dependency>
<groupId>dvp.spring.database</groupId>
<artifactId>generic-config-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
</plugin>
</plugins>
</build>
</project>
- regels 5-7: het door dit project gegenereerde Maven-artefact. Dit is hetzelfde als dat van het project [mysql-config-jpa-hibernate]. Dit betekent dat slechts één van deze projecten op een bepaald moment actief kan zijn;
- regels 10-14: het bovenliggende Maven-project dat de versie vastlegt van de meeste afhankelijkheden die het project nodig heeft;
- regels 19-23: de bibliotheek OpenJpa;
- regels 26-29: de Spring Data-bibliotheek;
- regels 32-34: het configuratieproject van de laag JPA is gebaseerd op dat van de configuratielaag JDBC, dat onder andere de driver JDBC van de gebruikte SGBD en de gegevens van de te gebruiken database;
- regels 35-40: het configuratieontwerp van de laag JDBC bevat de bibliotheek [Spring JDBC], die hier wordt vervangen door de bibliotheek [Spring Data JPA]. Daarom wordt aangegeven deze niet op te nemen in de afhankelijkheden van het project. Als deze toch blijft staan, leidt dit echter niet tot fouten;
Uiteindelijk zijn de afhankelijkheden als volgt:
![]() |
8.3.2. Spring-configuratie
![]() |
De klasse [ConfigJpa] configureert het Spring-project als volgt:
package generic.jpa.config;
import generic.jdbc.config.ConfigJdbc;
import javax.persistence.EntityManagerFactory;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@Import({ConfigJdbc.class})
public class ConfigJpa {
// de provider JPA
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
OpenJpaVendorAdapter openJpaVendorAdapter = new OpenJpaVendorAdapter();
openJpaVendorAdapter.setShowSql(false);
openJpaVendorAdapter.setDatabase(Database.MYSQL);
openJpaVendorAdapter.setGenerateDdl(true);
return openJpaVendorAdapter;
}
// entiteitspakketten JPA
public final static String[] ENTITIES_PACKAGES = { "generic.jpa.entities.dbproduitscategories" };
// gegevensbron
@Bean
public DataSource dataSource() {
// gegevensbron TomcatJdbc
DataSource dataSource = new DataSource();
// toegangscontrole JDBC
dataSource.setDriverClassName(ConfigJdbc.DRIVER_CLASSNAME);
dataSource.setUsername(ConfigJdbc.USER_DBPRODUITSCATEGORIES);
dataSource.setPassword(ConfigJdbc.PASSWD_DBPRODUITSCATEGORIES);
dataSource.setUrl(ConfigJdbc.URL_DBPRODUITSCATEGORIES);
// aanvankelijk geopende verbindingen
dataSource.setInitialSize(5);
// resultaat
return dataSource;
}
// EntityManagerFactory
@Bean
public EntityManagerFactory entityManagerFactory(JpaVendorAdapter jpaVendorAdapter, DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(jpaVendorAdapter);
factory.setPackagesToScan(ENTITIES_PACKAGES);
factory.setDataSource(dataSource);
factory.afterPropertiesSet();
return factory.getObject();
}
// Transactiemanager
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
Deze configuratie is vergelijkbaar met die beschreven in paragraaf 6.3.2, voor de Hibernate-implementatie JPA. We beschrijven alleen de verschillen:
- regels 23-30: de bean [jpaVendorAdapter] wordt nu geïmplementeerd met OpenJpa;
8.4. Het bestand [persistence.xml]
![]() |
<?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="generic-jpa-entities-dbproduitscategories" transaction-type="RESOURCE_LOCAL">
<!-- entiteiten JPA -->
<class>generic.jpa.entities.dbproduitscategories.Categorie</class>
<class>generic.jpa.entities.dbproduitscategories.Produit</class>
<class>generic.jpa.entities.dbproduitscategories.User</class>
<class>generic.jpa.entities.dbproduitscategories.Role</class>
<class>generic.jpa.entities.dbproduitscategories.UserRole</class>
<exclude-unlisted-classes />
</persistence-unit>
<persistence-unit name="generic-jpa-entities-dbproduits" transaction-type="RESOURCE_LOCAL">
<!-- entiteiten JPA -->
<class>generic.jpa.entities.dbproduits.Produit</class>
<exclude-unlisted-classes />
</persistence-unit>
</persistence>
- regel 4: de persistentie-eenheid die gekoppeld is aan de database [dbproduitscategories]. Deze kan een willekeurige naam hebben (attribuut name);
- regels 6-10: de vijf te beheren entiteiten JPA;
- regels 13-17: een andere persistentie-eenheid die gekoppeld is aan de database [dbproduits]. Met OpenJpa is het mogelijk om een persistentiebestand te hebben met meerdere persistentie-eenheden. Met EclipseLink is dit niet mogelijk. Ter herinnering: bij Hibernate is er geen persistentiebestand gebruikt;
8.5. De testlaag
![]() |
![]() |
De bovenstaande tests zijn identiek aan die van de Spring-implementaties JDBC, Spring JPA Hibernate en Spring JPA EclipseLink. Raadpleeg indien nodig de volgende pagina's:
- [JUnitTestCheckArguments]: paragraaf 4.11.1;
- [JUnitTestDao]: paragraaf 4.11.2;
- [JUnitTestPushTheLimits]: paragraaf 4.11.3;
- [JUnitTestProxies]: paragraaf 6.4.5;
De volgende uitvoeringsconfiguraties moeten worden gebruikt:
![]() | ![]() |
![]() | ![]() |
Om ervoor te zorgen dat de entiteiten JPA worden aangevuld (woven) door OpenJpa, moeten de Java-toepassingen of de tests JUnit worden gestart met een Java-agent. Deze agent zal de entiteiten JPA verrijken voordat deze worden geladen door JVM en [http://openjpa.apache.org/builds/1.2.3/apache-openjpa/docs/ref_guide_pc_enhance.html]. Laten we bijvoorbeeld eens kijken naar de configuratie van de test [JUnitTestDao]:
![]() |
- in het tabblad [Arguments] [1] wordt de referentie van de Java-agent opgegeven aan de JVM volgens de syntaxis [2]. De Java-agent is het archief [openjpa-<version>.jar] dat zich in de map [<m2-repo>/org/apache/openjpa/<version>] bevindt. De map <m2-repo> wordt opgegeven in de Eclipse-configuratie ([3] hieronder):
![]() |
In [2], hierboven, is gebruikgemaakt van een door de gebruiker gedefinieerde variabele [M2_REPO]:
![]() |
Aan de variabele [M2_REPO] is de waarde toegekend die zichtbaar is in [3].
De resultaten van de tests [JUnitTestDao] en [JUnitTestPushTheLimits] zijn als volgt:
![]() |
![]() |
![]() |
- in [1], [JUnitTestPushTheLimits-EclipseLink]: 70,583 s;
- in [2], [JUnitTestPushTheLimits-Hibernate]: 78,945 s;
- in [3], [JUnitTestPushTheLimits-JDBC]: 36,09 s;
- in [4], [JUnitTestPushTheLimits-OpenJpa]: 80,394 s;
De console-resultaten voor de test [JUnitTestProxies] zijn als volgt:
We zien hier dat wanneer we het veld [Categorie.produits] van een categorie van het type PROXY en het veld [Produit.categorie] van een product van het type PROXY openen, er in beide gevallen een verwijzing null is (regels 7 en 17).























