Skip to content

Commit

Permalink
#91 EclipseLink update integration works for now, cleanups are needed…
Browse files Browse the repository at this point in the history
… though
  • Loading branch information
s4ke committed Jul 27, 2015
1 parent cd743bf commit 84b83f0
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -239,20 +239,6 @@ public void delete(Class<?> entityClass, List<Class<?>> inIndexOf, Object id, Tr
else {
idValueForDeletion = id;
}
HSQuery hsQuery = this.searchIntegrator
.createHSQuery()
.targetedEntities( Collections.singletonList( indexClass ) )
.luceneQuery(
this.searchIntegrator.buildQueryBuilder()
.forEntity( indexClass )
.get()
.keyword()
.onField( field )
.matching( idValueForDeletion )
.createQuery()
);
int count = hsQuery.queryResultSize();
int processed = 0;
if ( indexClass.equals( entityClass ) ) {
this.searchIntegrator.getWorker().performWork(
new Work(
Expand All @@ -263,6 +249,20 @@ public void delete(Class<?> entityClass, List<Class<?>> inIndexOf, Object id, Tr
);
}
else {
HSQuery hsQuery = this.searchIntegrator
.createHSQuery()
.targetedEntities( Collections.singletonList( indexClass ) )
.luceneQuery(
this.searchIntegrator.buildQueryBuilder()
.forEntity( indexClass )
.get()
.keyword()
.onField( field )
.matching( idValueForDeletion )
.createQuery()
);
int count = hsQuery.queryResultSize();
int processed = 0;
// this was just contained somewhere
// so we have to update the containing entity
while ( processed < count ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ public void testManualIndexing() throws Exception {
FullTextEntityManager fem = this.searchFactory.getFullTextEntityManager( this.em );
fem.beginSearchTransaction();
Game newGame = new Game( "Legend of Zelda" );
newGame.setId( -10L );
fem.index( newGame );
fem.commitSearchTransaction();
Sleep.sleep(
Expand All @@ -254,6 +255,7 @@ public void testRollback() throws Exception {
fem.beginSearchTransaction();
Game newGame = new Game( "Pong" );
fem.index( newGame );
newGame.setId( -10L );
fem.rollbackSearchTransaction();
Sleep.sleep(
MAX_SLEEP_TIME, () -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ public void testManualIndexing() throws Exception {
FullTextEntityManager fem = this.searchFactory.getFullTextEntityManager( this.em );
fem.beginSearchTransaction();
Game newGame = new Game( "Legend of Zelda" );
newGame.setId( -10L );
fem.index( newGame );
fem.commitSearchTransaction();
Sleep.sleep(
Expand All @@ -260,6 +261,7 @@ public void testRollback() throws Exception {
FullTextEntityManager fem = this.searchFactory.getFullTextEntityManager( this.em );
fem.beginSearchTransaction();
Game newGame = new Game( "Pong" );
newGame.setId( -10L );
fem.index( newGame );
fem.rollbackSearchTransaction();
Sleep.sleep(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ public void testManualIndexing() throws Exception {
FullTextEntityManager fem = this.searchFactory.getFullTextEntityManager( this.em );
fem.beginSearchTransaction();
Game newGame = new Game( "Legend of Zelda" );
newGame.setId( -10L );
fem.index( newGame );
fem.commitSearchTransaction();
Sleep.sleep(
Expand All @@ -260,6 +261,7 @@ public void testRollback() throws Exception {
fem.beginSearchTransaction();
Game newGame = new Game( "Pong" );
fem.index( newGame );
newGame.setId( -10L );
fem.rollbackSearchTransaction();
Sleep.sleep(
MAX_SLEEP_TIME, () -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public static JPASearchFactoryController createSearchFactoryController(EntityMan
SEARCH_FACTORY_TYPE_DEFAULT_VALUE
);
//what AsyncUpdateSource to be used
SynchronizedUpdateSourceProvider synchronizedUpdateSourceProvider = (a, b, c, d, e) -> null;
SynchronizedUpdateSourceProvider synchronizedUpdateSourceProvider = (a, b, c, d, e, f, g) -> null;
AsyncUpdateSourceProvider asyncUpdateSourceProvider = (a, b, c, d, e, f) -> null;
if ( "sql".equals( type ) ) {
if ( emf == null ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import javax.persistence.EntityManagerFactory;
import javax.transaction.TransactionManager;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

Expand All @@ -17,6 +19,7 @@
import org.hibernate.search.genericjpa.JPASearchFactoryController;
import org.hibernate.search.genericjpa.events.impl.SynchronizedUpdateSource;
import org.hibernate.search.genericjpa.impl.SynchronizedUpdateSourceProvider;
import org.hibernate.search.genericjpa.metadata.impl.RehashedTypeMetadata;

/**
* Created by Martin on 27.07.2015.
Expand All @@ -26,6 +29,8 @@ public class EclipseLinkSynchronizedUpdateSourceProvider implements Synchronized
@Override
public SynchronizedUpdateSource getUpdateSource(
JPASearchFactoryController searchFactoryController,
Map<Class<?>, RehashedTypeMetadata> rehashedTypeMetadataPerIndexRoot,
Map<Class<?>, List<Class<?>>> containedInIndexOf,
Properties properties,
EntityManagerFactory emf,
TransactionManager transactionManager,
Expand All @@ -36,10 +41,12 @@ public SynchronizedUpdateSource getUpdateSource(

EclipseLinkUpdateSource eclipseLinkUpdateSource = new EclipseLinkUpdateSource(
searchFactoryController,
indexRelevantEntities
indexRelevantEntities,
rehashedTypeMetadataPerIndexRoot,
containedInIndexOf
);
for ( Class<?> entity : indexRelevantEntities ) {
if(session.getDescriptor( entity ) == null) {
if ( session.getDescriptor( entity ) == null ) {
//no JPA entity
continue;
}
Expand All @@ -49,7 +56,8 @@ public SynchronizedUpdateSource getUpdateSource(
}
session.getEventManager().addListener( eclipseLinkUpdateSource.sessionEventAspect );
return eclipseLinkUpdateSource;
} finally {
}
finally {
entityManager.close();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,62 @@
*/
package org.hibernate.search.genericjpa.db.events.eclipselink.impl;

import javax.persistence.EntityManagerFactory;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionEvent;
import org.eclipse.persistence.sessions.SessionEventAdapter;
import org.eclipse.persistence.sessions.UnitOfWork;

import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.search.backend.spi.SingularTermDeletionQuery;
import org.hibernate.search.backend.spi.Work;
import org.hibernate.search.backend.spi.WorkType;
import org.hibernate.search.bridge.FieldBridge;
import org.hibernate.search.bridge.StringBridge;
import org.hibernate.search.engine.ProjectionConstants;
import org.hibernate.search.engine.metadata.impl.DocumentFieldMetadata;
import org.hibernate.search.genericjpa.JPASearchFactoryController;
import org.hibernate.search.genericjpa.events.impl.SynchronizedUpdateSource;
import org.hibernate.search.genericjpa.factory.Transaction;
import org.hibernate.search.genericjpa.factory.impl.SubClassSupportInstanceInitializer;
import org.hibernate.search.genericjpa.metadata.impl.RehashedTypeMetadata;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.query.engine.spi.EntityInfo;
import org.hibernate.search.query.engine.spi.HSQuery;
import org.hibernate.search.spi.InstanceInitializer;

/**
* Created by Martin on 27.07.2015.
*/
public class EclipseLinkUpdateSource implements SynchronizedUpdateSource {

//TODO: use an abstraction of IndexUpdater here. we don't want the logic to be duplicated

private static final int HSQUERY_BATCH = 50;

private static Logger LOGGER = Logger.getLogger( EclipseLinkUpdateSource.class.getName() );

private static final InstanceInitializer INSTANCE_INITIALIZER = SubClassSupportInstanceInitializer.INSTANCE;

private final JPASearchFactoryController searchFactoryController;
private final Set<Class<?>> indexRelevantEntities;
private final Map<Class<?>, RehashedTypeMetadata> rehashedTypeMetadataPerIndexRoot;
private final Map<Class<?>, List<Class<?>>> containedInIndexOf;

final DescriptorEventAspect descriptorEventAspect;
final SessionEventAspect sessionEventAspect;
Expand All @@ -45,43 +70,50 @@ public class EclipseLinkUpdateSource implements SynchronizedUpdateSource {

public EclipseLinkUpdateSource(
JPASearchFactoryController searchFactoryController,
Set<Class<?>> indexRelevantEntities) {
Set<Class<?>> indexRelevantEntities,
Map<Class<?>, RehashedTypeMetadata> rehashedTypeMetadataPerIndexRoot,
Map<Class<?>, List<Class<?>>> containedInIndexOf) {
this.searchFactoryController = searchFactoryController;
this.indexRelevantEntities = indexRelevantEntities;
this.descriptorEventAspect = new DescriptorEventAspect();
this.sessionEventAspect = new SessionEventAspect();
this.rehashedTypeMetadataPerIndexRoot = rehashedTypeMetadataPerIndexRoot;
this.containedInIndexOf = containedInIndexOf;
}

private class DescriptorEventAspect extends DescriptorEventAdapter {

@Override
public void postInsert(DescriptorEvent event) {
Object entity = event.getObject();
Class<?> entityClass = INSTANCE_INITIALIZER.getClass( entity );
if ( EclipseLinkUpdateSource.this.indexRelevantEntities.contains( entityClass ) ) {
LOGGER.fine( "Insert Event for " + entity );
Session session = event.getSession();
if(session.isUnitOfWork()) {
if ( session.isUnitOfWork() ) {
session = ((UnitOfWork) session).getParent();
}
FullTextEntityManager fem = EclipseLinkUpdateSource.this.fullTextEntityManagers.get( session );
fem.index( entity );
}
}

@Override
public void postUpdate(DescriptorEvent event) {
Object entity = event.getObject();
Class<?> entityClass = INSTANCE_INITIALIZER.getClass( entity );
if ( EclipseLinkUpdateSource.this.indexRelevantEntities.contains( entityClass ) ) {
LOGGER.fine( "Update Event for " + entity );
Session session = event.getSession();
if(session.isUnitOfWork()) {
if ( session.isUnitOfWork() ) {
session = ((UnitOfWork) session).getParent();
}
FullTextEntityManager fem = EclipseLinkUpdateSource.this.fullTextEntityManagers.get( session );
fem.index( entity );
}
}

@Override
public void postDelete(DescriptorEvent event) {
//we have to do stuff similar to IndexUpdater here.
//we have to check in which index this object was found and
Expand All @@ -94,19 +126,94 @@ public void postDelete(DescriptorEvent event) {
if ( EclipseLinkUpdateSource.this.indexRelevantEntities.contains( entityClass ) ) {
LOGGER.fine( "Delete Event for " + entity );
Session session = event.getSession();
if(session.isUnitOfWork()) {
if ( session.isUnitOfWork() ) {
session = ((UnitOfWork) session).getParent();
}
FullTextEntityManager fem = EclipseLinkUpdateSource.this.fullTextEntityManagers.get( session );
Object id = session.getId( entity );
fem.purge( entityClass, (Serializable) id );
List<Class<?>> inIndexOf = EclipseLinkUpdateSource.this.containedInIndexOf.get( entityClass );
for ( Class<?> indexClass : inIndexOf ) {
RehashedTypeMetadata metadata = EclipseLinkUpdateSource.this.rehashedTypeMetadataPerIndexRoot.get(
indexClass
);

XProperty idProperty = metadata.getIdPropertyAccessorForType().get( entityClass );
Object id = idProperty.invoke( entity );

List<String> fields = metadata.getIdFieldNamesForType().get( entityClass );
for ( String field : fields ) {
DocumentFieldMetadata metaDataForIdField = metadata.getDocumentFieldMetadataForIdFieldName()
.get(
field
);

SingularTermDeletionQuery.Type idType = metadata.getSingularTermDeletionQueryTypeForIdFieldName()
.get( entityClass );
Object idValueForDeletion;
if ( idType == SingularTermDeletionQuery.Type.STRING ) {
FieldBridge fb = metaDataForIdField.getFieldBridge();
if ( !(fb instanceof StringBridge) ) {
throw new IllegalArgumentException( "no TwoWayStringBridge found for field: " + field );
}
idValueForDeletion = ((StringBridge) fb).objectToString( id );
}
else {
idValueForDeletion = id;
}

if ( indexClass.equals( entityClass ) ) {
fem.purge( entityClass, (Serializable) id );
}
else {
FullTextQuery fullTextQuery = fem.createFullTextQuery(
fem.getSearchFactory()
.buildQueryBuilder()
.forEntity( indexClass )
.get()
.keyword()
.onField( field )
.matching( idValueForDeletion )
.createQuery(), indexClass
);

fullTextQuery.setMaxResults( HSQUERY_BATCH );
fullTextQuery.setProjection( ProjectionConstants.ID );

int count = fullTextQuery.getResultSize();
int processed = 0;
// this was just contained somewhere
// so we have to update the containing entity
while ( processed < count ) {
fullTextQuery.setFirstResult( processed );
for ( Object[] projection : (List<Object[]>) fullTextQuery.getResultList() ) {
Serializable originalId = (Serializable) projection[0];
ReadObjectQuery nativeQuery = new ReadObjectQuery();
nativeQuery.setReferenceClass( indexClass );
nativeQuery.setSelectionId( originalId );
nativeQuery.setCacheUsage( ObjectLevelReadQuery.DoNotCheckCache );
Object original = session.executeQuery( nativeQuery );
if ( original != null ) {
fem.index( original );
}
else {
// original is not available in the
// database, but it will be deleted by its
// own delete event
// TODO: log this?
}
}
processed += HSQUERY_BATCH;
}
}
}
}
}
}

}

private class SessionEventAspect extends SessionEventAdapter {

@Override
public void postBeginTransaction(SessionEvent event) {
Session session = event.getSession();
FullTextEntityManager fem = EclipseLinkUpdateSource.this.fullTextEntityManagers.get( session );
Expand All @@ -120,6 +227,7 @@ public void postBeginTransaction(SessionEvent event) {
}
}

@Override
public void postCommitTransaction(SessionEvent event) {
Session session = event.getSession();
FullTextEntityManager fem = EclipseLinkUpdateSource.this.fullTextEntityManagers.get( session );
Expand All @@ -134,6 +242,7 @@ public void postCommitTransaction(SessionEvent event) {
}
}

@Override
public void postRollbackTransaction(SessionEvent event) {
Session session = event.getSession();
FullTextEntityManager fem = EclipseLinkUpdateSource.this.fullTextEntityManagers.get( session );
Expand Down
Loading

0 comments on commit 84b83f0

Please sign in to comment.