Bredex

Mandantenfähigkeit mit Hibernate (ohne Hibernate shards)

Ein Laptop, der auf seinem Bildschirm eine Reihe von Codezeilen anzeigt.

Zur Realisierung von Mandantenfähigkeit in einer Anwendung verwenden wir unterschiedliche DB-Schemata. Dies hat den Vorteil, dass die Daten pro Mandant in eigenen Tabellen liegen und auf Datenbankebene die Berechtigungen gesteuert werden können. In unserem Fall existiert ein Schema für gemeinsam genutzte (Stamm-) Daten. Pro Mandant gibt es ein weiteres Schema für die mandantenspezifischen Daten, wobei die Mandanten-Schemata alle identisch aufgebaut sind.

Die Entities für die Stammdaten werden in JPA mit der @Table-Annotation versehen, wobei das Schema-Attribut jeweils angegeben wird: @Table(name=”…”, schema=”<Stammdatenschema>”)
Bei den Entities für die mandantenspezifischen Daten wird das Schema-Attribut in der @Table-Annotation nicht angegeben: @Table(name=”…”). Hier greift das Default-Schema, welches Hibernate dann automatisch in den generierten SQL-Statements vor die Tabellennamen setzt. Das Default-Schema kann in der persistence.xml festgelegt werden:

<persistence-unit name=”…”>
    …
    <properties>
        <property name=”hibernate.default_schema” value=”…”/>
        …
    </properties>
</persistence-unit>

Pro Mandant wird eine eigene Persistence-Unit mit entsprechendem Default-Schema definiert. Im Application Server existiert zu jeder Persistence-Unit ein zugehöriger Entity-Manager. Bei einer Client-Anfrage entscheidet der Server anhand der User-ID, zu welchem Mandant der User gehört und verwendet dann für die Datenbank-Zugriffe den korrespondierenden Entity-Manager.

Alternativ könnte man nachträglich die generierten SQL-Statements manipulieren und das Schema anpassen. Hibernate bietet hierzu die Möglichkeit, einen Interceptor (org.hibernate.Interceptor) in der persistence.xml zu registrieren, der über entsprechende Callback-Methoden vor der Ausführung von DB-Operationen benachrichtigt wird:

<persistence-unit name=”…”>
    …
    <properties>
        <property name=”hibernate.ejb.interceptor”    
                  value=”<MeineInterceptorKlasse>” />
        …
    </properties>
</persistence-unit>

In der Methode onPrepareStatement(String) wird das von Hibernate generierte SQL-Statement als Parameter übergeben und kann vor der Ausführung noch verändert werden, da das von der Methode zurückgelieferte Statement ausgeführt wird.

Fazit: Die erste Variante ist sicherlich die robustere Lösung, während man mit der Interceptor-Lösung die vollständige Kontrolle über die von Hibernate abgesetzten DB-Statements erlangt.

Autor

Michael Buchholz

Michael Buchholz

Jobs

DevSecOps Engineer (m/w/d)

Du suchst nach dem nächsten Karriereschritt? Dann freuen wir uns auf deine Bewerbung! ... Weiterlesen

Praktikum

Sammle wertvolle Praxiserfahrung bei der BREDEX und gewinne erste Einblicke in das Unternehmen ... Weiterlesen

Ihr Ansprechpartner

Tim Winselmann

Tim Winselmann

Head of Software Development

Gerne erzählen wir Ihnen mehr zu diesem Thema.

Beitrag teilen

Facebook
Twitter
LinkedIn
XING
Email
WhatsApp

Diese Beiträge könnten Sie auch interessieren

2024 © BREDEX GmbH