Guía de Interceptores en Hibernate

interceptores en Hibernate

interceptores en Hibernate


En esta entrada vamos ver una guía de interceptores en Hibernate, para poder aplicarlos y utilizarlos en función de ciertos eventos que se puedan producir en nuestra aplicación.

¿Qué es Hibernate?

Hibernate es un ORM (Object Relational Mapping) para Java que nos va a permitir realizar los mapeos de nuestros objetos con un Base de Datos relacional. Proporciona un framework con el que poder interactuar y crear nuestras relaciones y consultas contra la Base de Datos.

¿Qué son los interceptores de Hibernate?

Los interceptores de Hibernate son una interfaz que nos permite reaccionar ante cierto tipo de eventos que ocurren en Hibernate.

Los interceptores, una vez registrados, permiten la comunicación entre nuestra aplicación y la session de Hibernate.

Para poder llevar a cabo la creación de un interceptor en Hibernate, podemos utilizar dos aproximaciones diferentes:

  • hacer uso de la interfaz Interceptor de Hibernate
  • extender de la clase EmptyInterceptor

Por ejemplo, los interceptores de Hibernate podríamos decir que funcionan de manera similar al @Prepersist y @PreUpdate de JPA.

Una vez se ha creado el interceptor es necesario registrarlo, lo cual lo podemos hacer mediante Session-scoped o sessionFactory-scoped.

Creación de interceptor en Hibernate extendiendo de EmptyInterceptor

Extendiendo de la clase EmptyInterceptor podemos crear un interceptor en Hibernate de una manera sencilla y rápida. Únicamente es necesario sobre escribir los métodos que necesitemos de la clase EmptyInterceptor:

public class HibernateCustomInterceptor extends EmptyInterceptor {

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

Otros métodos que podemos sobreescribir son onLoad, onDelete o onFlushDirty.

Interceptor en Hibernate implementando la clase Interceptor

Esta aproximación permite implementar 15 métodos de la clase Interceptor de Hibernate. Si no necesitamos ninguna implementación especial o adicional no es necesario.

public class HibernateCustomInterceptor implements Interceptor, Serializable {

    @Override
    public boolean onLoad(Object entity, Serializable id, 
      Object[] state, String[] propertyNames, Type[] types) 
      throws CallbackException {
        
        return false;
    }

   

    @Override
    public String onPrepareStatement(String sql) {
        // do something  
        return sql;
    }

......

}

Registro de Interceptor de Hibernate con Session-scoped

Una vez hemos creado nuestro interceptor vamos a registrarlo haciendo uso de Session-scoped. Un interceptor registrado como Session-scoped se vincula a una session específica de Hibernate:

public static Session sessionWithInterceptor(Interceptor interceptor) 
  throws IOException {
    return getSessionFactory().withOptions()
      .interceptor(interceptor).openSession();
}

public static SessionFactory getSessionFactory(String propertyFileName) throws IOException {
        if (sessionFactory == null) {
            ServiceRegistry serviceRegistry = configureServiceRegistry();
            sessionFactory = getSessionFactoryBuilder(serviceRegistry).build();
        }
        return sessionFactory;
}

Registro de Interceptor de Hibernate con SessionFactory-scoped

Con la aproximación de registrar un interceptor de Hibernate con SessionFatory-scoped, se va a registrar antes de construir la SessionFactory.

Para realizar el registro del interceptor se realiza a través del método applyInterceptor del SessionFactoryBuilder.

ServiceRegistry serviceInterceptorRegistry = configureServiceRegistry();
SessionFactory sessionFactory = getSessionFactoryBuilder(serviceInterceptorRegistry)
  .applyInterceptor(new CustomInterceptor())
  .build();



    private static ServiceRegistry configureServiceRegistry() throws IOException {
        Properties properties = getProperties();
        return new StandardServiceRegistryBuilder().applySettings(properties)
            .build();
    }

    private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) {
        
        MetadataSources metadataSources = new MetadataSources(serviceRegistry);
        metadataSources.addPackage("com.refactorizando.example.hibernate.interceptors");
        metadataSources.addAnnotatedClass(User.class);

        Metadata metadata = metadataSources.buildMetadata();
        return metadata.getSessionFactoryBuilder();

    }

Cuando realizamos un registro mediante esta aproximación, el interceptor será aplicado a todas las sesiones de Hibernate.

Para evitar problemas concurrentes y que el interceptor sean thread-safe necesitamos especificar el contexto de la sesión de hibernate mediante una propiedad en nuestro fichero de configuración:

hibernate:
  current_session_context_class: org.hibernate.context.internal.ThreadLocalSessionContext

Conclusión

En esta pequeña guía de Interceptores en Hibernate hemos visto las diferentes aproximaciones para registrar e implementar un interceptor en Hibernate. El uso de interceptores en Hibernate nos va a permitir reaccionar ante algunos eventos como por ejemplo al hacer save() y de esta manera poder interactuar con la Session de Hibernate añadiendo o modificando antes de guardar.

Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *