NHibernate EventListeners

English post

En este post comentábamos sobre StatelessSession como nueva feature de NHibernate, ahora bien, otra de las features disponibles en el trunk de NHibernate (portada de Hibernate) son los EventListeners. Con ellos podemos interceptar acciones llevadas a cabo por NHibernate antes o después de que se realicen como por ejemplo un Save, Update, Load, Flush entre otras.

En este ejemplo vamos a realizar acciones antes y después de que se ejecute el comando Save(object).

Definimos el EventListener:

public class MySaveEventListener : NHibernate.Event.Default.DefaultSaveOrUpdateEventListener
{
    protected override void CascadeBeforeSave(IEventSource source, IEntityPersister persister,
                                              object entity, object anything)
    {
        Console.WriteLine(“Before Save the entity “ + entity);
        base.CascadeBeforeSave(source,persister,entity,anything);
    }

    protected override void CascadeAfterSave(IEventSource source, IEntityPersister persister,
                                             object entity, object anything)
    {
        Console.WriteLine(“After Save the entity “ + entity);
        base.CascadeAfterSave(source,persister,entity,anything);
    }
}

Y para configurarlo programaticamente con el SessionFactory hacemos: 

Configuration cfg = new Configuration();

cfg.Configure(“hibernate.cfg.xml”);

cfg.SetListener(ListenerType.Save, new MySaveEventListener());

Ahora realizamos un Save: 

using (ISessionFactory sf = cfg.BuildSessionFactory())
{
    using (ISession session = sf.OpenSession())
    {
        Foo f1 = new Foo();
        f1.Misc = “m1″;
        f1.Name = “n1″;

        session.Save(f1);

        session.Flush();
    }
}

Y este es el resultado de la consola, incluyendo el SQL que NHibernate generó: 

Before Save the entity Entity Foo:0:n1
NHibernate: INSERT INTO Foo (Name, Misc) VALUES (@p0, @p1); select SCOPE_IDENTIT
Y(); @p0 = 'n1', @p1 = 'm1'
After Save the entity Entity Foo:1:n1

Foo tiene un object id como Integer e Identity. Antes de guardarse la property Id tiene como valor 0, despues del Save tiene como valor 1 (debido a que es el primer objeto en la base).

3 comments so far

  1. Fabio Maulo Octubre 8, 2007 20:53

    La verdad ya no recuerdo los metodos que dejé virtual para ser sobreescrito…
    lo voy a revisar cuando termine de portar Statistics.

    De todas formas yo evitaría de sobreescribir metodos de los eventos de default ya que si bien se puede “intervenir” en lo que NH hace, tambien se pueden hacer montones de desastres. NH usa los eventos para hacer lo que ante hacía con codigo incrustado todo en la Session.

    Los Listeners se pueden configurar usando el hibernate.cfg.xml y sería mejor que cada uno escriba sus propios eventos y lo configure.
    Lo listeners trabajan similar los eventos de NET con lo cual se pude configurar hasta el orden en como los eventos se ejecutan y se puede modificar los varios “EventArgs”. Queda claro que modifican los argumentos del evento tambien se pueden hacer desastres pero, por lo menos, son mas limitados.
    Cabe destacar que la lista que se configura es exactamente la que NH ejecuta… por lo tanto no hay que olvidarse de poner tambien el evento de default.

    Fabio.

  2. Dario Quintana Octubre 8, 2007 21:09

    Gracias por el aviso Fabio !

    Según ejemplos que ví en java, por lo general lo declaran así (obviamente, estas lineas son c# pero la idea es la misma):
    protected override void CascadeBeforeSave(IEventSource source, IEntityPersister persister,
    object entity, object anything)
    {
    Console.WriteLine(”Before Save the entity ” + entity);
    base.CascadeBeforeSave(source,persister,entity,anything);
    }

    Es decir, le agregan la linea que omití en el ejemplo y lo voy a corregir:

    base.CascadeBeforeSave(source,persister,entity,anything);

    Entonces si NHibernate debe realizar algo, lo hace, aunque sigue librada la posibilidad de error.

  3. [...] principal caracterista para sacarle ventajas a NHibernate 2.0 es Event Listeners. En chat con Fabio [...]

Leave a comment

Please be polite and on topic. Your e-mail will never be published.