2023.06 2024.06

Datenbank - JPA

Diese Dokumentationsseite beschreibt die Integration der Java Persistence API (JPA)

Allgemeines

Die Java Persistence API (JPA) ist eine Spezifikation für das Speichern, Aktualisieren und Abrufen von Daten in Java-Anwendungen. MyCoRe verwendet JPA, um die Datenbankanbindung zu realisieren.

Konfiguration

bis Version 2024.06

Grundsätzlich bringt der MyCoRe-Kern bereits alle erforderlichen Grundeinstellungen mit. Lediglich die Konfigurationsdatei persistence.xml muss in den Konfigurationsordner abgelegt werden. Hier sind nur noch einige wenige Parameter wie der Datenbankname MY_DATABASE, das Schema MY_SCHEMA, der Datenbankbenutzer DATABASE_USER und das Passwort DATABASE_PASSWORD anzupassen. Je nach verwendeter MyCoRe-Komponente müssen weitere Mapping-Dateien hinzugefügt oder entfernt werden.

MyCoRe-Komponente Mapping-Datei
mycore-base META-INF/mycore-base-mappings.xml
mycore-user2 META-INF/mycore-user2-mappings.xml
mycore-acl META-INF/mycore-acl-mappings.xml
mycore-iview2 META-INF/mycore-iview2-mappings.xml
mycore-pi META-INF/mycore-pi-mappings.xml
mycore-viewer META-INF/mycore-viewer-mappings.xml
mycore-jobqueue META-INF/mycore-jobqueue-mappings.xml
persistence.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">
    <persistence-unit name="MyCoRe" transaction-type="RESOURCE_LOCAL">

        <mapping-file>META-INF/mycore-base-mappings.xml</mapping-file>
        <mapping-file>META-INF/mycore-ifs-mappings.xml</mapping-file>
        <mapping-file>META-INF/mycore-iview2-mappings.xml</mapping-file>
        <mapping-file>META-INF/mycore-pi-mappings.xml</mapping-file>
        <mapping-file>META-INF/mycore-user2-mappings.xml</mapping-file>
        <mapping-file>META-INF/mycore-jobqueue-mappings.xml</mapping-file>

        <properties>

            <!--  PostgreSQL -->
            <property name="jakarta.persistence.jdbc.driver" value="org.postgresql.Driver"/>
            <property name="jakarta.persistence.jdbc.url"
                      value="jdbc:postgresql://127.0.0.1/MY_DATABASE?currentSchema=MY_SCHEMA"/>

            <property name="jakarta.persistence.jdbc.user" value="DATABASE_USER"/>
            <property name="jakarta.persistence.password" value="DATABASE_PASSWORD"/>

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

            <!-- second-level cache  -->
            <property name="hibernate.cache.region.factory_class"
                      value="org.hibernate.cache.internal.NoCachingRegionFactory"/>
            <property name="hibernate.cache.use_second_level_cache" value="false"/>
            <property name="hibernate.cache.use_query_cache" value="false"/>

            <!-- Set batch_size to "0" in case of SQL batch Errors -->
            <property name="hibernate.jdbc.batch_size" value="2000"/>
            <property name="hibernate.default_batch_fetch_size" value="100"/>

            <!-- Echo all executed SQL to stdout -->
            <property name="hibernate.show.sql" value="true"/>
            <property name="hibernate.format.sql" value="true"/>

            <!-- Homepage: https://github.com/brettwooldridge/HikariCP -->
            <property name="hibernate.connection.provider_class" value="org.hibernate.hikaricp.internal.HikariCPConnectionProvider" />
            <property name="hibernate.hikari.maximumPoolSize" value="30" />
            <property name="hibernate.hikari.leakDetectionThreshold" value="9000" />
            <property name="hibernate.hikari.registerMbeans" value="true" />

        </properties>
    </persistence-unit>
</persistence>

Konfigurationsdatei: resources/META-INF/persistence.xml

Außerdem muss für die Verwendung von HikariCP der Treiber in der pom.xml der Anwendung hinzugefügt werden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-hikaricp</artifactId>
    <version>${hibernate.version}</version>
</dependency>
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version>
</dependency>

pom.xml

ab Version 2024.06

Ab Release 2024.06 wird empfohlen die Konfiguration über die mycore.properties zu realisieren. Die persistence.xml wird weiterhin unterstützt, jedoch bietet die Konfiguration per mycore.properties einige Vorteile.

  • Die Mappings werden automatisch konfiguriert, je nachdem welche MyCoRe-Komponenten in der Anwendung verwendet werden.
  • Die Konfiguration ist einfacher und übersichtlicher.
  • Die Konfiguration kann bereits in der jar-Datei enthalten sein und URLs, Passwörter und Benutzer können in der mycore.properties im Konfigurationsverzeichnis überschrieben werden.
Beispiel für die Konfiguration per mycore.properties:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
MCR.JPA.PersistenceUnit.MyCoRe.Class=org.mycore.backend.jpa.MCRSimpleConfigPersistenceUnitDescriptor
MCR.JPA.User=pguser
MCR.JPA.Password=password
MCR.JPA.Driver=org.postgresql.Driver
MCR.JPA.URL=jdbc:postgresql://db:5432/mir
MCR.JPA.Hbm2ddlAuto=update
MCR.JPA.Connection.ProviderClass=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
MCR.JPA.Connection.MaximumPoolSize=30
MCR.JPA.Connection.MinimumIdle=2
MCR.JPA.Connection.IdleTimeout=30000
MCR.JPA.Connection.MaxLifetime=180000
MCR.JPA.Connection.LeakDetectionThreshold=9000
MCR.JPA.Connection.RegisterMbeans=true

Konfigurationsdatei: mycore.properties

Erweiterte Konfiguration und interne Details

Die Konfiguration erfolgt über PersistenceUnitDescriptors, die die Konfiguration der JPA-Verbindung steuern. Es können verschiedene Implementierungen von PersistenceUnitDescriptors verwendet werden, welche über das Konzept der konfigurierbaren Klasseninstanzen mit dem Property MCR.JPA.PersistenceUnit.DescriptorName.Class konfiguriert werden.

Der verwendete PersistenceUnitDescriptor wird über das Property MCR.JPA.PersistenceUnitName mit dem Standardwert MyCoRe Konfiguriert. MyCoRe bringt die beiden Standardimplementierungen org.mycore.backend.jpa.MCRPersistenceUnitDescriptor und org.mycore.backend.jpa.MCRSimpleConfigPersistenceUnitDescriptor mit.

Die Klasse org.mycore.backend.jpa.MCRPersistenceUnitDescriptor bietet folgende Konfigurationsmöglichkeiten:
Property Persistence.xml equivalent Standardproperty Standardwert
MCR.JPA.PersistenceUnit.MyCoRe.PersistenceProviderClassName persistence/persistence-unit/provider MCR.JPA.ProviderClassName org.hibernate.jpa.HibernatePersistenceProvider
MCR.JPA.PersistenceUnit.MyCoRe.TransactionType persistence/persistence-unit@transaction-type MCR.JPA.TransactionType RESOURCE_LOCAL
MCR.JPA.PersistenceUnit.MyCoRe.ValidationMode persistence/persistence-unit/validation-mode MCR.JPA.ValidationMode AUTO
MCR.JPA.PersistenceUnit.MyCoRe.SharedCacheMode persistence/persistence-unit/shared-cache-mode MCR.JPA.SharedCacheMode NONE
MCR.JPA.PersistenceUnit.MyCoRe.ManagedClassNames persistence/persistence-unit/class MCR.JPA.ManagedClassNames
MCR.JPA.PersistenceUnit.MyCoRe.MappingFileNames persistence/persistence-unit/mapping-file MCR.JPA.MappingFileNames Je nach verwendeten Modul

Die Properties innerhalb des <properties> Elements in der persistence.xml werden über die Standard JPA-Property-Namen in Kombination mit dem Prefix MCR.JPA.PersistenceUnit.MyCoRe.Properties. konfiguriert, z.B.

1
MCR.JPA.PersistenceUnit.MyCoRe.Properties.jakarta.persistence.jdbc.url=jdbc:postgresql://localhost:5432/mycore

Konfigurationsdatei: mycore.properties

JPA Property MyCoRe Property
jakarta.persistence.jdbc.driver MCR.JPA.Driver
jakarta.persistence.jdbc.url MCR.JPA.URL
jakarta.persistence.jdbc.user MCR.JPA.User
jakarta.persistence.jdbc.password MCR.JPA.Password
hibernate.cache.use_second_level_cache MCR.JPA.Cache.UseSecondLevelCache
hibernate.cache.use_query_cache MCR.JPA.Cache.UseQueryCache
hibernate.cache.region.factory_class MCR.JPA.Cache.RegionFactoryClass
hibernate.globally_quoted_identifiers_skip_column_definitions MCR.JPA.GloballyQuotedIdentifiers.SkipColumnDefinitions
hibernate.globally_quoted_identifiers MCR.JPA.GloballyQuotedIdentifiers
hibernate.show_sql MCR.JPA.ShowSql
hibernate.hbm2ddl.auto MCR.JPA.Hbm2ddlAuto
hibernate.default_schema MCR.JPA.DefaultSchema
hibernate.connection.provider_class MCR.JPA.Connection.ProviderClass
hibernate.hikari.maximumPoolSize MCR.JPA.Connection.MaximumPoolSize
hibernate.hikari.minimumIdle MCR.JPA.Connection.MinimumIdle
hibernate.hikari.idleTimeout MCR.JPA.Connection.IdleTimeout
hibernate.hikari.maxLifetime MCR.JPA.Connection.MaxLifetime
hibernate.hikari.connectionTimeout MCR.JPA.Connection.ConnectionTimeout
hibernate.hikari.leakDetectionThreshold MCR.JPA.Connection.LeakDetectionThreshold
hibernate.hikari.registerMbeans MCR.JPA.Connection.RegisterMbeans

Die Klasse MCRSimpleConfigPersistenceUnitDescriptor erweitert MCRPersistenceUnitDescriptor und bietet einfachere Alternativen zur Konfiguration der Properties, um die Länge der Properties zu reduzieren und die Namenskonventionen von MyCoRe einzuhalten.

Datenbank-Treiber

Der für den Zugriff auf die Datenbank notwendige JDBC-Treiber (i.d.R. eine JAR-Datei) kann im lib Ordner des Konfigurationsverzeichnisses abgelegt werden. Alternativ kann der Treiber auch in der pom.xml der Anwendung als Dependency hinzugefügt werden. Dies funktioniert jedoch nur, wenn die Anwendung als WAR-Datei verpackt wird.

Hinweis bei Performance-Problemen

Sollten in der Anwendung vermehrt Meldungen wie Connection leak detection triggered auftauchen, dann ist das ein Hinweis, dass Verbindungen nicht rechtzeitig geschlossen werden. Das kann daran liegen, dass ein langwieriger Prozess läuft. In diesem Fall kann die hibernate.hikari.leakDetectionThreshold erhöht werden. HikariCP überprüft in regelmäßigen Abständen, ob eine Verbindung länger als die angegebene Zeit offen ist. Ist das der Fall, wird eine Warnung ausgegeben. Der Standardwert beträgt 2 Sekunden. Der Wert wird in Millisekunden angegeben. Sollte der Wert auf 0 gesetzt werden, wird die Überprüfung deaktiviert. Sollte die Meldung jedoch auch bei kurzen Prozessen auftreten, dann sollte die Anwendung genauer untersucht werden, um die Ursache zu finden. Es handelt sich in der Regel um ein Problem im Programmcode der Anwendung, das behoben werden muss. Es ist nicht empfehlenswert, die Verbindungen automatisch durch den Pool schließen zu lassen.

HikariCP does not, in principle, believe that the pool should coverup connection leaks. We disagree with the reasoning behind C3P0's unreturned connection handling. The leak detection is there to help you pinpoint the source of the leak. That should provide enough clues to track down the configuration or coding error.

1
2
 <!-- Meldungen erst ab 30 Sekunden anzeigen -->
 <property name="hibernate.hikari.leakDetectionThreshold" value="30000" />

Konfiguration per persistence.xml: resources/META-INF/persistence.xml

1
2
 # Meldungen erst ab 30 Sekunden anzeigen
 MCR.JPA.Connection.LeakDetectionThreshold=30000

Konfiguration per mycore.properties: mycore.properties