Skip to content

Commit

Permalink
HSEARCH-3269 Replace Hib criterion with JPA criteria
Browse files Browse the repository at this point in the history
  • Loading branch information
fax4ever committed Oct 15, 2020
1 parent 1d6e5ac commit b37411c
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.EntityManagerFactory;
import javax.persistence.criteria.Predicate;

import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.search.batch.jsr352.logging.impl.Log;
import org.hibernate.search.batch.jsr352.massindexing.MassIndexingJobParameters.Defaults;
import org.hibernate.search.batch.jsr352.massindexing.impl.util.SerializationUtil;
import org.hibernate.search.batch.jsr352.massindexing.impl.util.ValidationUtil;
import org.hibernate.search.util.common.SearchException;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;

/**
Expand Down Expand Up @@ -107,7 +107,7 @@ public static class ParametersBuilder {
private Integer checkpointInterval;
private Integer rowsPerPartition;
private Integer maxThreads;
private Set<Criterion> customQueryCriteria;
private Set<Predicate> customQueryCriteria;
private String customQueryHql;
private Integer maxResultsPerEntity;
private String tenantId;
Expand Down Expand Up @@ -331,22 +331,22 @@ public ParametersBuilder purgeAllOnStart(boolean purgeAllOnStart) {
}

/**
* Add criterion to construct a customized selection of mass-indexing under the criteria approach. You
* can call this method multiple times to add multiple criteria: only entities matching every criterion
* Add predicate to construct a customized selection of mass-indexing under the criteria approach. You
* can call this method multiple times to add multiple criteria: only entities matching every predicate
* will be indexed. However, mixing this approach with the HQL restriction is not allowed.
*
* @param criterion criterion.
* @param predicate predicate.
*
* @return itself
*/
public ParametersBuilder restrictedBy(Criterion criterion) {
public ParametersBuilder restrictedBy(Predicate predicate) {
if ( customQueryHql != null ) {
throw new IllegalArgumentException( "Cannot use HQL approach and Criteria approach in the same time." );
}
if ( criterion == null ) {
throw new NullPointerException( "The criterion is null." );
if ( predicate == null ) {
throw new NullPointerException( "The predicate is null." );
}
customQueryCriteria.add( criterion );
customQueryCriteria.add( predicate );
return this;
}

Expand Down Expand Up @@ -453,7 +453,7 @@ public Properties build() {
);
}
catch (IOException e) {
throw log.failedToSerializeJobParameter( Criteria.class, e );
throw log.failedToSerializeJobParameter( Predicate.class, e );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.EntityManagerFactory;
import javax.persistence.criteria.Predicate;

import org.hibernate.criterion.Criterion;
import org.hibernate.search.batch.jsr352.massindexing.impl.util.EntityTypeDescriptor;

/**
Expand All @@ -34,7 +34,7 @@ public class JobContextData {
*/
private Map<String, EntityTypeDescriptor> entityTypeDescriptorMap;

private Set<Criterion> customQueryCriteria;
private Set<Predicate> customQueryCriteria;

public JobContextData() {
entityTypeDescriptorMap = new HashMap<>();
Expand Down Expand Up @@ -80,11 +80,11 @@ public Class<?> getEntityType(String entityName) {
return getEntityTypeDescriptor( entityName ).getJavaClass();
}

public Set<Criterion> getCustomQueryCriteria() {
public Set<Predicate> getCustomQueryCriteria() {
return customQueryCriteria;
}

public void setCustomQueryCriteria(Set<Criterion> criteria) {
public void setCustomQueryCriteria(Set<Predicate> criteria) {
this.customQueryCriteria = criteria;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import javax.batch.runtime.context.JobContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.criteria.Predicate;

import org.hibernate.Criteria;
import org.hibernate.search.batch.jsr352.context.jpa.spi.EntityManagerFactoryRegistry;
import org.hibernate.search.batch.jsr352.inject.scope.spi.HibernateSearchJobScoped;
import org.hibernate.search.batch.jsr352.massindexing.MassIndexingJobParameters.Defaults;
Expand Down Expand Up @@ -200,7 +200,7 @@ private void validateQuerying() {
SerializationUtil.parseCacheModeParameter( CACHE_MODE, serializedCacheMode, Defaults.CACHE_MODE );

if ( StringHelper.isNotEmpty( serializedCustomQueryCriteria ) ) {
SerializationUtil.parseParameter( Criteria.class, CUSTOM_QUERY_HQL, serializedCustomQueryCriteria );
SerializationUtil.parseParameter( Predicate.class, CUSTOM_QUERY_HQL, serializedCustomQueryCriteria );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Set;
import javax.batch.api.BatchProperty;
import javax.batch.api.chunk.AbstractItemReader;
Expand All @@ -25,17 +26,16 @@
import javax.inject.Named;
import javax.persistence.EntityManagerFactory;
import javax.persistence.LockModeType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.query.Query;
import org.hibernate.search.batch.jsr352.context.jpa.spi.EntityManagerFactoryRegistry;
import org.hibernate.search.batch.jsr352.inject.scope.spi.HibernateSearchPartitionScoped;
Expand Down Expand Up @@ -358,31 +358,39 @@ private FetchingStrategy createCriteriaFetchingStrategy(
Class<?> entityType = jobData.getEntityType( entityName );
Object upperBound = SerializationUtil.deserialize( serializedUpperBound );
Object lowerBound = SerializationUtil.deserialize( serializedLowerBound );
Set<Criterion> customQueryCriteria = jobData.getCustomQueryCriteria();
Set<Predicate> customQueryCriteria = jobData.getCustomQueryCriteria();

EntityTypeDescriptor typeDescriptor = jobData.getEntityTypeDescriptor( entityType );
IdOrder idOrder = typeDescriptor.getIdOrder();

return (session, lastCheckpointInfo) -> {
Criteria criteria = new CriteriaImpl( entityType.getName(), session.unwrap( SessionImplementor.class ) );
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<?> criteria = builder.createQuery( entityType );
Root<?> root = criteria.from( entityType );

// build orders for this entity
idOrder.addAscOrder( criteria );
idOrder.addAscOrder( builder, criteria, root );

ArrayList<Predicate> predicates = new ArrayList<>( customQueryCriteria.size() + 1 );

// build criteria using job context data
customQueryCriteria.forEach( c -> criteria.add( c ) );
predicates.addAll( customQueryCriteria );

// build criteria using bounds
if ( upperBound != null ) {
criteria.add( idOrder.idLesser( upperBound ) );
predicates.add( idOrder.idLesser( builder, root, upperBound ) );
}
if ( lastCheckpointInfo != null ) {
criteria.add( idOrder.idGreater( lastCheckpointInfo.getLastProcessedEntityId() ) );
predicates.add( idOrder.idGreater( builder, root, lastCheckpointInfo.getLastProcessedEntityId() ) );
}
else if ( lowerBound != null ) {
criteria.add( idOrder.idGreaterOrEqual( lowerBound ) );
predicates.add( idOrder.idGreaterOrEqual( builder, root, lowerBound ) );
}

criteria.where( predicates.toArray( new Predicate[predicates.size()] ) );

Query<?> query = session.createQuery( criteria );

if ( maxResults != null ) {
int remaining;
if ( lastCheckpointInfo != null ) {
Expand All @@ -391,16 +399,17 @@ else if ( lowerBound != null ) {
else {
remaining = maxResults;
}
criteria.setMaxResults( remaining );
query.setMaxResults( remaining );
}

return criteria.setReadOnly( true )
.setCacheable( false )
.setLockMode( LockMode.NONE )
.setFlushMode( FlushMode.MANUAL )
.setCacheMode( cacheMode )
.setFetchSize( entityFetchSize )
.scroll( ScrollMode.FORWARD_ONLY );
return query
.setReadOnly( true )
.setCacheable( false )
.setLockMode( LockModeType.NONE )
.setCacheMode( cacheMode )
.setHibernateFlushMode( FlushMode.MANUAL )
.setFetchSize( entityFetchSize )
.scroll( ScrollMode.FORWARD_ONLY );
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/
package org.hibernate.search.batch.jsr352.massindexing.impl.step.lucene;

import org.hibernate.Criteria;

/**
* The index scope of a given entity type.
*
Expand All @@ -19,7 +17,7 @@ public enum IndexScope {
*/
HQL,
/**
* Index entities restricted the {@link Criteria} given by user.
* Index entities restricted the {@link javax.persistence.criteria.Predicate} given by user.
*/
CRITERIA,
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@
import javax.batch.runtime.context.JobContext;
import javax.inject.Inject;
import javax.persistence.EntityManagerFactory;
import javax.persistence.LockModeType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.StatelessSession;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Projections;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.query.Query;
import org.hibernate.search.batch.jsr352.logging.impl.Log;
import org.hibernate.search.batch.jsr352.massindexing.MassIndexingJobParameters;
import org.hibernate.search.batch.jsr352.massindexing.MassIndexingJobParameters.Defaults;
Expand Down Expand Up @@ -158,14 +160,14 @@ public PartitionPlan mapPartitions() throws Exception {
break;

case CRITERIA:
partitionBounds = buildPartitionUnitsFrom( ss, entityTypeDescriptors.get( 0 ),
partitionBounds = buildPartitionUnitsFrom( emf, ss, entityTypeDescriptors.get( 0 ),
jobData.getCustomQueryCriteria(), maxResults, idFetchSize, rowsPerPartition,
IndexScope.CRITERIA );
break;

case FULL_ENTITY:
for ( EntityTypeDescriptor entityTypeDescriptor : entityTypeDescriptors ) {
partitionBounds.addAll( buildPartitionUnitsFrom( ss, entityTypeDescriptor,
partitionBounds.addAll( buildPartitionUnitsFrom( emf, ss, entityTypeDescriptor,
Collections.emptySet(), maxResults, idFetchSize, rowsPerPartition,
IndexScope.FULL_ENTITY ) );
}
Expand Down Expand Up @@ -207,8 +209,8 @@ public PartitionPlan mapPartitions() throws Exception {
}
}

private List<PartitionBound> buildPartitionUnitsFrom(StatelessSession ss,
EntityTypeDescriptor entityTypeDescriptor, Set<Criterion> customQueryCriteria,
private List<PartitionBound> buildPartitionUnitsFrom(EntityManagerFactory emf, StatelessSession ss,
EntityTypeDescriptor entityTypeDescriptor, Set<Predicate> customQueryCriteria,
Integer maxResults, int fetchSize, int rowsPerPartition,
IndexScope indexScope) {
Class<?> javaClass = entityTypeDescriptor.getJavaClass();
Expand All @@ -217,19 +219,31 @@ private List<PartitionBound> buildPartitionUnitsFrom(StatelessSession ss,
Object lowerID = null;
Object upperID = null;

Criteria criteria = new CriteriaImpl( javaClass.getName(), (SharedSessionContractImplementor) ss );
entityTypeDescriptor.getIdOrder().addAscOrder( criteria );
CriteriaBuilder builder = emf.getCriteriaBuilder();
CriteriaQuery<?> criteria = builder.createQuery( javaClass );
Root<?> root = criteria.from( javaClass );

if ( maxResults != null ) {
criteria.setMaxResults( maxResults );
}
criteria.setProjection( Projections.id() )
.setFetchSize( fetchSize )
entityTypeDescriptor.getIdOrder().addAscOrder( builder, criteria, root );

EntityType<?> model = root.getModel();
Class<?> javaType = model.getIdType().getJavaType();

@SuppressWarnings("rawtypes")
SingularAttribute singularAttribute = model.getId( javaType );
criteria.select( root.get( singularAttribute ) );

Query<?> query = ss.createQuery( criteria );

query.setFetchSize( fetchSize )
.setReadOnly( true )
.setCacheable( false )
.setLockMode( LockMode.NONE );
.setLockMode( LockModeType.NONE );

if ( maxResults != null ) {
query.setMaxResults( maxResults );
}

try ( ScrollableResults scroll = criteria.scroll( ScrollMode.SCROLL_SENSITIVE ) ) {
try ( ScrollableResults scroll = query.scroll( ScrollMode.SCROLL_SENSITIVE ) ) {
/*
* The scroll results are originally positioned *before* the first element,
* so we need to scroll rowsPerPartition + 1 positions to advanced to the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@
import javax.batch.runtime.context.StepContext;
import javax.inject.Inject;
import javax.persistence.EntityManagerFactory;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Projections;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.query.Query;
import org.hibernate.search.batch.jsr352.logging.impl.Log;
import org.hibernate.search.batch.jsr352.massindexing.MassIndexingJobParameters;
import org.hibernate.search.batch.jsr352.massindexing.impl.JobContextData;
Expand Down Expand Up @@ -68,7 +67,7 @@ public void beforeStep() {
JobContextData jobData = (JobContextData) jobContext.getTransientUserData();
EntityManagerFactory emf = jobData.getEntityManagerFactory();

Set<Criterion> customQueryCriteria = jobData.getCustomQueryCriteria();
Set<Predicate> customQueryCriteria = jobData.getCustomQueryCriteria();
IndexScope indexScope = PersistenceUtil.getIndexScope( customQueryHql, customQueryCriteria );
BiFunction<Session, Class<?>, Long> rowCountFunction;
switch ( indexScope ) {
Expand Down Expand Up @@ -108,13 +107,16 @@ public void afterStep() {
stepContext.setPersistentUserData( stepProgress );
}

private static Long rowCountCriteria(Session session, Class<?> entityType, Set<Criterion> customQueryCriteria) {
Criteria criteria = new CriteriaImpl( entityType.getName(), session.unwrap( SessionImplementor.class ) );
private static Long rowCountCriteria(Session session, Class<?> entityType, Set<Predicate> predicates) {
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Long> criteria = builder.createQuery( Long.class );
criteria.select( builder.count( criteria.from( entityType ) ) );
criteria.where( predicates.toArray( new Predicate[predicates.size()] ) );

customQueryCriteria.forEach( c -> criteria.add( c ) );

return (Long) criteria.setProjection( Projections.rowCount() )
.setCacheable( false )
Query<Long> query = session.createQuery( criteria );
query.setCacheable( false )
.uniqueResult();

return query.getSingleResult();
}
}

0 comments on commit b37411c

Please sign in to comment.