Hibernate presretači

1. Pregled

U ovoj ćemo raspravi razmotriti razne načine presretanja operacija u apstrahiranom provođenju relacijskog mapiranja Hibernate.

2. Definiranje presijecača hibernacije

Hibernate Interceptor je sučelje koje nam omogućuje da reagiramo na određene događaje u hibernaciji.

Ti su presretači registrirani kao povratni pozivi i pružaju komunikacijske veze između sesije Hibernate i aplikacije. Takvim povratnim pozivom aplikacija može presresti osnovne operacije hibernacije kao što su spremanje, ažuriranje, brisanje itd.

Postoje dva načina definiranja presretača:

  1. provedba org.hibernate.Interceptor sučelje
  2. produžujući org.hibernate.EmptyInterceptor razred

2.1. Provođenje Presretač Sučelje

Provedba org.hibernate.Interceptor zahtijeva provedbu oko 14 popratnih metoda. Te metode uključuju onLoad, onSave, onDelete, findDirty, i još nekoliko.

Također je važno osigurati da bilo koja klasa koja implementira Interceptor sučelje ima mogućnost serializacije (implementira java.io.Serializable).

Tipičan primjer izgledao bi ovako:

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

Ako nema posebnih zahtjeva, produžujući EmptyInterceptor klase i toplo se preporučuje samo nadjačavanje potrebnih metoda.

2.2. Proširivanje EmptyInterceptor

Proširivanje org.hibernate.EmptyInterceptor klasa pruža lakši način definiranja presretača. Sada trebamo nadjačati metode koje se odnose na operaciju koju želimo presresti.

Na primjer, možemo definirati svoj CustomInterceptor kao:

javna klasa CustomInterceptor proširuje EmptyInterceptor {}

A ako moramo presresti operacije spremanja podataka prije nego što se izvrše, moramo nadjačati onSave metoda:

@Override public boolean onSave (Object entity, Serializable id, Object [] state, String [] propertyNames, Type [] types) {if (entity instanceof User) {logger.info (((User) entity) .toString ()) ; } return super.onSave (entitet, id, stanje, svojstvaName, vrste); }

Primijetite kako ova implementacija jednostavno ispisuje entitet - ako je to Korisnik.

Iako je moguće vratiti vrijednost od pravi ili lažno, dobra je praksa dopustiti širenje onSave događaj pozivanjem super.onSave ().

Drugi slučaj upotrebe bio bi pružanje revizijskog traga za interakcije s bazom podataka. Možemo koristiti onFlushDirty () metoda da se zna kada se entitet promijeni.

Za Korisnik objekt, možemo odlučiti da ga ažuriramo zadnja promjena svojstvo date kad god se mijenja na entitetima tipa Korisnik dogoditi se.

To se može postići sa:

@Override public boolean onFlushDirty (Entitet objekta, Serializable id, Object [] currentState, Object [] previousState, String [] propertyNames, Type [] vrste) {if (entitet instanceof User) {((User) entitet) .setLastModified (novo Datum()); logger.info (((Korisnikov) entitet) .toString ()); } vrati super.onFlushDirty (entitet, id, currentState, previousState, propertyNames, vrste); }

Ostali događaji poput izbrisati i opterećenje (inicijalizacija objekta) može se presresti implementacijom odgovarajućeg onDelete i onLoad metode odnosno.

3. Registriranje Presretači

Presretač hibernacije može se registrirati kao Sjednica-skopski ili SjednicaFaktivni opseg.

3.1. Presretač s opsegom zasjedanja

A Sjednica-scoped presretač povezan je s određenom sesijom. Stvara se kad se sesija definira ili otvori kao:

javna statička sesija getSessionWithInterceptor (Interceptor interceptor) baca IOException {return getSessionFactory (). withOptions () .interceptor (interceptor) .openSession (); }

U gore navedenom izričito smo registrirali presretač s određenom hibernacijom.

3.2. SjednicaTvornica-skopsko Presretač

A SessionFactory-presretač s opsegom registrira se prije izgradnje a SjednicaTvornica. To se obično radi putem applyInterceptor metoda na a SessionFactoryBuilder primjer:

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

Važno je napomenuti da a SessionFactory-presretač s opsegom primijenit će se na sve sesije. Stoga moramo biti oprezni da ne pohranimo specifično stanje sesije - jer će ovaj presretač istovremeno koristiti različite sesije.

Za ponašanje specifično za sesiju, preporučuje se eksplicitno otvaranje sesije s drugim presretačem kao što je ranije prikazano.

Za SjednicaTvornicas preskočenim presretačima, naravno, moramo osigurati da budu zaštićeni od niti. To se može postići specificiranjem konteksta sesije u datoteci svojstava:

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

Ili dodavanjem ovog u našu XML konfiguracijsku datoteku:

 org.hibernate.context.internal.ThreadLocalSessionContext 

Također, kako bi se osigurala serializacija, SjednicaTvornica-preskočeni presretači moraju implementirati readResolve metoda Serijalizirati sučelje.

4. Zaključak

Vidjeli smo kako definirati i registrirati presretače hibernacije ili kao Sjednica-skopski ili SjednicaTvornica-skopsko. U oba slučaja moramo osigurati da se presretači mogu serializirati, posebno ako želimo serijsku sesiju.

Ostale alternative presretačima uključuju Hibernate Events i JPA Callback.

Kao i uvijek, na Githubu možete provjeriti cjeloviti izvorni kod.