GEDOPLAN
Jakarta EE (Java EE)Spring

Globale Entity-Filter mit Hibernate @Filter

Jakarta EE (Java EE)Spring
coffee gee8e882c6 640
coffee gee8e882c6 640

Dank JPQL oder der Criteria API sind Queries keine große Sache. Doch oft entsteht in Projekten die Anforderung, Daten basierend auf z.B. Berechtigungen zu filtern. Alle Abfragen mit entsprechenden where-Clauseln zu versehen mag pragmatisch sein, ist aber sehr anfällig für Fehler und die Wartbarkeit leidet.

Hibernate bietet für genauso diesen Zweck @Filter Annotation an, die es uns erlauben auf Entity-Ebene Filter zu deklarieren, die bei Bedarf aktiviert werden können. Die Definition solcher Filter geschieht per Annotation auf z.B. der Entity selbst oder aber auch auf Package Ebene:

@FilterDefs(
        @FilterDef(
                name = FilterNames.BY_MATERIAL_NUMBER,
                parameters = @ParamDef(name = FilterNames.BY_MATERIAL_NUMBER_P_PREFIX, type = "string"),
                defaultCondition = "material_number like :" + FilterNames.BY_MATERIAL_NUMBER_P_PREFIX
        )
)

Unser Filter definiert einen Namen (der später dazu verwendet, wird die, Aktivierung durchzuführen), ein oder mehrere Parameter und natürlich die konkrete SQL Kondition.

Dieser Filter muss nun lediglich auf Entity-Ebene durch eine entsprechende Annotation konfiguriert werden

@Entity
@Filter(name = FilterNames.BY_MATERIAL_NUMBER)
public class Material {...}

Solche Filter sind per Default deaktiviert und müssen nun für die aktive Hibernate Session aktiviert werden. Dies lässt sich über den Entitymanager ganz leicht durchführen

Session session = em.unwrap(Session.class);
Filter filter = session.enableFilter(FilterNames.BY_MATERIAL_NUMBER);
filter.setParameter(FilterNames.BY_MATERIAL_NUMBER_P_PREFIX, "99%");

em.createQuery(...)

In der laufenden Session werden jetzt alle Queries, die direkt “Material” adressieren, zusätzlich mit unserem Filter versehen. Wichtig: das betrifft lediglich alle Filter Queries, ein direktes Laden über die Id mittels z.B. “load” führt keine Filterung durch und auch das Laden abhängiger Entities (OneToMany, ManyToMany) bedarf zusätzlicher Annotationen (@FilterJoinTable).

Filter by Default

Oft wollen wir solche Filter immer aktivieren, um z.B. über die Berechtigungen des Users Einschränkungen durchzuführen. In Spring Boot bietet sich dafür eine Customizer Methode an

@Configuration
public class MaterialFilter {
    @Bean
    @ConditionalOnMissingBean
    public PlatformTransactionManager transactionManager(
            ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
        JpaTransactionManager transactionManager = new JpaTransactionManager() {
            @Override
            protected EntityManager createEntityManagerForTransaction() {
                final EntityManager entityManager = super.createEntityManagerForTransaction();
                Session session = entityManager.unwrap(Session.class);
                activateMaterialFilterByRole(session); // read roles, activate filter, set parameters
                return entityManager;
            }
        };
        transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
        return transactionManager;
    }

(als Alternative wäre auch eine Lösung mittels AOP Methoden möglich)

Und wie immer hier noch mal alles Live und in Farbe: https://github.com/GEDOPLAN/hibernate-filter

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Kurse

weitere Blogbeiträge

flasks 606612 640
Web Security, Webprogrammierung

Keycloak + Protractor E2E Test

Keycloak ist eine charmante Authentifizierungs-Lösung die sich dank keycloak-angular relativ Problemlos in der eigenen Anwendung verankern lässt. Im Arbeitsalltag stolpert…

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!