Interceptors in slaapstand

1. Overzicht

In deze discussie zullen we kijken naar verschillende manieren om bewerkingen te onderscheppen binnen Hibernate's geabstraheerde relationele mapping-implementatie.

2. Hibernate Interceptors definiëren

De Hibernate Interceptor is een interface waarmee we kunnen reageren op bepaalde gebeurtenissen binnen Hibernate.

Deze interceptors worden geregistreerd als callbacks en zorgen voor communicatieverbindingen tussen de sessie van Hibernate en de applicatie. Met een dergelijke callback kan een toepassing de kernbewerkingen van Hibernate onderscheppen, zoals opslaan, bijwerken, verwijderen, etc.

Er zijn twee manieren om interceptors te definiëren:

  1. implementatie van de org.hibernate.Interceptor koppel
  2. uitbreiding van de org.hibernate.EmptyInterceptor klasse

2.1. Implementeren van een Onderschepper Koppel

Implementeren org.hibernate.Interceptor vereist implementatie van ongeveer 14 begeleidende methoden. Deze methoden omvatten onLoad, onSave, onDelete, findDirty, en nog een paar.

Het is ook belangrijk om ervoor te zorgen dat elke klasse die de Interceptor-interface implementeert, serialiseerbaar is (implementeert java.io.Serializable).

Een typisch voorbeeld zou er als volgt uitzien:

public class CustomInterceptorImpl implementeert Interceptor, Serializable {@Override public boolean onLoad (Object entity, Serializable id, Object [] state, String [] propertyNames, Type [] types) gooit CallbackException {// ... return false; } // ... @Override public String onPrepareStatement (String sql) {// ... return sql; }}

Als er geen speciale vereisten zijn, uitbreiding van de EmptyInterceptor class en alleen het overschrijven van de vereiste methoden wordt sterk aanbevolen.

2.2. Verlengend EmptyInterceptor

Uitbreiding van het org.hibernate.EmptyInterceptor class biedt een gemakkelijkere manier om een ​​interceptor te definiëren. We hoeven nu alleen de methoden te overschrijven die betrekking hebben op de operatie die we willen onderscheppen.

We kunnen bijvoorbeeld onze CustomInterceptor net zo:

openbare klasse CustomInterceptor breidt EmptyInterceptor {} uit

En als we gegevensbesparende bewerkingen moeten onderscheppen voordat ze worden uitgevoerd, moeten we deze overschrijven onSave methode:

@Override public boolean onSave (Object entiteit, Serializable id, Object [] staat, String [] propertyNames, Type [] types) {if (entiteitsinstantie van Gebruiker) {logger.info (((Gebruiker) entiteit) .toString ()) ; } retourneer super.onSave (entiteit, id, staat, propertyNames, types); }

Merk op hoe deze implementatie eenvoudig de entiteit afdrukt - als het een Gebruiker.

Hoewel het mogelijk is om een ​​waarde te retourneren van waar of false, is het een goede gewoonte om verspreiding van onSave evenement door een beroep te doen op super.onSave ().

Een andere use-case zou het bieden van een audittrail voor database-interacties zijn. We kunnen de onFlushDirty () methode om te weten wanneer een entiteit verandert.

Voor de Gebruiker object, kunnen we besluiten om zijn laatst gewijzigd date eigenschap wanneer wijzigingen op entiteiten van het type Gebruiker gebeuren.

Dit kan worden bereikt met:

@Override public boolean onFlushDirty (Object entiteit, Serializable id, Object [] currentState, Object [] previousState, String [] propertyNames, Type [] types) {if (entiteitsinstantie van Gebruiker) {((Gebruiker) entiteit) .setLastModified (nieuw Datum()); logger.info (((Gebruiker) entiteit) .toString ()); } retourneer super.onFlushDirty (entiteit, id, currentState, previousState, propertyNames, types); }

Andere evenementen zoals verwijderen en laden (objectinitialisatie) kan worden onderschept door het overeenkomstige onDelete en onLoad methoden respectievelijk.

3. Registreren Onderscheppers

Een Hibernate-interceptor kan worden geregistreerd als Sessie-scoped of SessionFactory-bereik.

3.1. Interceptor met sessiebereik

EEN Sessie-scoped interceptor is gekoppeld aan een specifieke sessie. Het wordt gemaakt wanneer de sessie wordt gedefinieerd of geopend als:

openbare statische sessie getSessionWithInterceptor (Interceptor interceptor) gooit IOException {return getSessionFactory (). withOptions () .interceptor (interceptor) .openSession (); }

In het bovenstaande hebben we expliciet een interceptor geregistreerd met een bepaalde slaapsessie.

3.2. SessionFactory-scoped Onderschepper

EEN SessionFactory-scoped interceptor wordt geregistreerd voordat een SessionFactory. Dit wordt meestal gedaan via de applyInterceptor methode op een SessionFactoryBuilder voorbeeld:

ServiceRegistry serviceRegistry = configureServiceRegistry (); SessionFactory sessionFactory = getSessionFactoryBuilder (serviceRegistry) .applyInterceptor (nieuwe CustomInterceptor ()) .build ();

Het is belangrijk op te merken dat a SessionFactory-scoped interceptor wordt op alle sessies toegepast. Daarom moeten we oppassen dat we geen sessiespecifieke status opslaan - aangezien deze interceptor door verschillende sessies tegelijkertijd zal worden gebruikt.

Voor sessiespecifiek gedrag wordt aanbevolen om expliciet een sessie te openen met een andere interceptor, zoals eerder getoond.

Voor SessionFactory-scoped interceptors, we moeten er natuurlijk voor zorgen dat het thread-safe is. Dit kan worden bereikt door een sessiecontext op te geven in het eigenschappenbestand:

hibernate.current_session_context_class = org.hibernate.context.internal.ThreadLocalSessionContext

Of door dit toe te voegen aan ons XML-configuratiebestand:

 org.hibernate.context.internal.ThreadLocalSessionContext 

Om serialiseerbaarheid te garanderen, SessionFactory-scoped onderscheppers moeten de readResolve methode van de Serialiseerbaar koppel.

4. Conclusie

We hebben gezien hoe we Hibernate-interceptors kunnen definiëren en registreren als Sessie-scoped of SessionFactory-scoped. In beide gevallen moeten we ervoor zorgen dat de interceptors serialiseerbaar zijn, vooral als we een serialiseerbare sessie willen.

Andere alternatieven voor interceptors zijn onder meer Hibernate Events en JPA Callbacks.

En, zoals altijd, kun je de volledige broncode bekijken op Github.


$config[zx-auto] not found$config[zx-overlay] not found