All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hibernate.jpa.event.spi.JpaIntegrator Maven / Gradle / Ivy
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.jpa.event.spi;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.internal.MetadataImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.DuplicationStrategy;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener;
import org.hibernate.jpa.event.internal.core.JpaAutoFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaDeleteEventListener;
import org.hibernate.jpa.event.internal.core.JpaFlushEntityEventListener;
import org.hibernate.jpa.event.internal.core.JpaFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaMergeEventListener;
import org.hibernate.jpa.event.internal.core.JpaPersistEventListener;
import org.hibernate.jpa.event.internal.core.JpaPersistOnFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostDeleteEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostInsertEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostLoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostUpdateEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveOrUpdateEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.hibernate.jpa.event.spi.jpa.ListenerFactoryBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
/**
* Hibernate EntityManager specific Integrator, performing JPA setup.
*
* @author Steve Ebersole
*/
public class JpaIntegrator implements Integrator {
private ListenerFactory jpaListenerFactory;
private CallbackBuilder callbackBuilder;
private CallbackRegistryImpl callbackRegistry;
private CascadeStyle oldPersistCascadeStyle;
private static final DuplicationStrategy JPA_DUPLICATION_STRATEGY = new JPADuplicationStrategy();
/**
* Perform integration.
*
* @param metadata The "compiled" representation of the mapping information
* @param sessionFactory The session factory being created
* @param serviceRegistry The session factory's service registry
*/
public void integrate(
Metadata metadata,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
// first, register the JPA-specific persist cascade style
try {
oldPersistCascadeStyle = CascadeStyles.getCascadeStyle( "persist" );
}
catch (Exception e) {
}
CascadeStyles.registerCascadeStyle(
"persist",
new PersistCascadeStyle()
);
// then prepare listeners
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
eventListenerRegistry.addDuplicationStrategy( JPA_DUPLICATION_STRATEGY );
// op listeners
eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, JpaAutoFlushEventListener.INSTANCE );
eventListenerRegistry.setListeners( EventType.DELETE, new JpaDeleteEventListener() );
eventListenerRegistry.setListeners( EventType.FLUSH_ENTITY, new JpaFlushEntityEventListener() );
eventListenerRegistry.setListeners( EventType.FLUSH, JpaFlushEventListener.INSTANCE );
eventListenerRegistry.setListeners( EventType.MERGE, new JpaMergeEventListener() );
eventListenerRegistry.setListeners( EventType.PERSIST, new JpaPersistEventListener() );
eventListenerRegistry.setListeners( EventType.PERSIST_ONFLUSH, new JpaPersistOnFlushEventListener() );
eventListenerRegistry.setListeners( EventType.SAVE, new JpaSaveEventListener() );
eventListenerRegistry.setListeners( EventType.SAVE_UPDATE, new JpaSaveOrUpdateEventListener() );
// post op listeners
eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_LOAD, new JpaPostLoadEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_UPDATE, new JpaPostUpdateEventListener() );
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
for ( Map.Entry entry : ( (Map) cfgService.getSettings() ).entrySet() ) {
if ( !String.class.isInstance( entry.getKey() ) ) {
continue;
}
final String propertyName = (String) entry.getKey();
if ( !propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) {
continue;
}
final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 );
final EventType eventType = EventType.resolveEventTypeByName( eventTypeName );
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( String listenerImpl : ( (String) entry.getValue() ).split( " ," ) ) {
eventListenerGroup.appendListener( instantiate( listenerImpl, serviceRegistry ) );
}
}
// handle JPA "entity listener classes"...
final ReflectionManager reflectionManager = ( (MetadataImpl) metadata ).getMetadataBuildingOptions()
.getReflectionManager();
this.callbackRegistry = new CallbackRegistryImpl();
this.jpaListenerFactory = ListenerFactoryBuilder.buildListenerFactory( sessionFactory.getSessionFactoryOptions() );
this.callbackBuilder = new CallbackBuilderLegacyImpl( jpaListenerFactory, reflectionManager );
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have non java class persisted by hibernate
continue;
}
callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
}
for ( EventType eventType : EventType.values() ) {
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( Object listener : eventListenerGroup.listeners() ) {
if ( CallbackRegistryConsumer.class.isInstance( listener ) ) {
( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( callbackRegistry );
}
}
}
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
if ( oldPersistCascadeStyle == null ) {
CascadeStyles.registerCascadeStyle(
"persist",
null
);
}
CascadeStyles.registerCascadeStyle(
"persist",
(CascadeStyles.BaseCascadeStyle) oldPersistCascadeStyle
);
if ( callbackRegistry != null ) {
callbackRegistry.release();
}
if ( callbackBuilder != null ) {
callbackBuilder.release();
}
if ( jpaListenerFactory != null ) {
jpaListenerFactory.release();
}
}
private Object instantiate(String listenerImpl, ServiceRegistryImplementor serviceRegistry) {
try {
return serviceRegistry.getService( ClassLoaderService.class ).classForName( listenerImpl ).newInstance();
}
catch (Exception e) {
throw new HibernateException( "Could not instantiate requested listener [" + listenerImpl + "]", e );
}
}
private static class PersistCascadeStyle extends CascadeStyles.BaseCascadeStyle {
@Override
public boolean doCascade(CascadingAction action) {
return action == JpaPersistEventListener.PERSIST_SKIPLAZY
|| action == CascadingActions.PERSIST_ON_FLUSH;
}
@Override
public String toString() {
return "STYLE_PERSIST_SKIPLAZY";
}
}
private static class JPADuplicationStrategy implements DuplicationStrategy {
@Override
public boolean areMatch(Object listener, Object original) {
return listener.getClass().equals( original.getClass() ) &&
HibernateEntityManagerEventListener.class.isInstance( original );
}
@Override
public Action getAction() {
return Action.KEEP_ORIGINAL;
}
}
}