package org.hibernate.cache.internal;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.jboss.logging.Logger;
public class CollectionCacheInvalidator implements Integrator, PostInsertEventListener, PostDeleteEventListener,
PostUpdateEventListener {
private static final Logger LOG = Logger.getLogger( CollectionCacheInvalidator.class.getName() );
@Override
public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
integrate( serviceRegistry, sessionFactory );
}
@Override
public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
integrate( serviceRegistry, sessionFactory );
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
}
@Override
public void onPostInsert(PostInsertEvent event) {
evictCache( event.getEntity(), event.getPersister(), event.getSession(), null );
}
@Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return true;
}
@Override
public void onPostDelete(PostDeleteEvent event) {
evictCache( event.getEntity(), event.getPersister(), event.getSession(), null );
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
evictCache( event.getEntity(), event.getPersister(), event.getSession(), event.getOldState() );
}
private void integrate(SessionFactoryServiceRegistry serviceRegistry, SessionFactoryImplementor sessionFactory) {
if ( !sessionFactory.getSettings().isAutoEvictCollectionCache() ) {
return;
}
if ( !sessionFactory.getSettings().isSecondLevelCacheEnabled() ) {
return;
}
EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
eventListenerRegistry.appendListeners( EventType.POST_INSERT, this );
eventListenerRegistry.appendListeners( EventType.POST_DELETE, this );
eventListenerRegistry.appendListeners( EventType.POST_UPDATE, this );
}
private void evictCache(Object entity, EntityPersister persister, EventSource session, Object[] oldState) {
try {
SessionFactoryImplementor factory = persister.getFactory();
Set<String> collectionRoles = factory.getCollectionRolesByEntityParticipant( persister.getEntityName() );
if ( collectionRoles == null || collectionRoles.isEmpty() ) {
return;
}
for ( String role : collectionRoles ) {
CollectionPersister collectionPersister = factory.getCollectionPersister( role );
if ( !collectionPersister.hasCache() ) {
continue;
}
String mappedBy = collectionPersister.getMappedByProperty();
if ( mappedBy != null ) {
int i = persister.getEntityMetamodel().getPropertyIndex( mappedBy );
Serializable oldId = null;
if ( oldState != null ) {
oldId = session.getIdentifier( oldState[i] );
}
Object ref = persister.getPropertyValue( entity, i );
Serializable id = null;
if ( ref != null ) {
id = session.getIdentifier( ref );
}
if ( id != null && !id.equals( oldId ) ) {
evict( id, collectionPersister, session );
if ( oldId != null ) {
evict( oldId, collectionPersister, session );
}
}
}
else {
LOG.debug( "Evict CollectionRegion " + role );
collectionPersister.getCacheAccessStrategy().evictAll();
}
}
}
catch ( Exception e ) {
LOG.error( "", e );
}
}
private void evict(Serializable id, CollectionPersister collectionPersister, EventSource session) {
LOG.debug( "Evict CollectionRegion " + collectionPersister.getRole() + " for id " + id );
CacheKey key = session.generateCacheKey( id, collectionPersister.getKeyType(), collectionPersister.getRole() );
collectionPersister.getCacheAccessStrategy().evict( key );
}
}