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

IT-Training - GEDOPLAN
Webprogrammierung

Angular Directive, Hostbinding

Directive sind neben Komponenten eines der zentralen Konzepte in Angular. Anders als Components bringt eine Directive kein eigenes Template mit,…
pages g14a0ddbef 640
Spring

Spring Boot + Jasper Font Extensions

Jasper Reports bietet in der Java-Welt eine tolle Möglichkeit, um Reports für die unterschiedlichsten Einsatzzwecke zu generieren. Gerade im Zusammenspiel…

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!