Skip to content

Commit

Permalink
OGM-1038 Make it possible for the dialects to access the transaction …
Browse files Browse the repository at this point in the history
…context
  • Loading branch information
DavideD authored and gsmet committed Jun 2, 2016
1 parent c67936d commit 1779831
Show file tree
Hide file tree
Showing 28 changed files with 297 additions and 176 deletions.
Expand Up @@ -490,7 +490,7 @@ public Number nextValue(NextValueRequest request) {

@Override
public ClosableIterator<Tuple> executeBackendQuery(
BackendQuery<String> query, QueryParameters queryParameters) {
BackendQuery<String> query, QueryParameters queryParameters, TupleContext tupleContext) {

Object[] parameters = new Object[queryParameters.getPositionalParameters().size()];
int i = 0;
Expand Down Expand Up @@ -521,7 +521,7 @@ public ClosableIterator<Tuple> executeBackendQuery(
}

@Override
public int executeBackendUpdateQuery(BackendQuery<String> query, QueryParameters queryParameters) {
public int executeBackendUpdateQuery(BackendQuery<String> query, QueryParameters queryParameters, TupleContext tupleContext) {
// TODO implement. org.hibernate.ogm.datastore.mongodb.MongoDBDialect.executeBackendUpdateQuery(BackendQuery<MongoDBQueryDescriptor>, QueryParameters) might be helpful as a reference.
throw new UnsupportedOperationException("Not yet implemented.");
}
Expand Down
Expand Up @@ -10,6 +10,7 @@
import org.hibernate.ogm.dialect.spi.AssociationContext;
import org.hibernate.ogm.dialect.spi.AssociationTypeContext;
import org.hibernate.ogm.dialect.spi.GridDialect;
import org.hibernate.ogm.dialect.spi.TransactionContext;
import org.hibernate.ogm.model.spi.Association;
import org.hibernate.ogm.model.spi.Tuple;
import org.hibernate.ogm.util.impl.Contracts;
Expand All @@ -25,21 +26,26 @@ public class AssociationContextImpl implements AssociationContext {
private final AssociationTypeContext associationTypeContext;
private final OperationsQueue operationsQueue;
private final Tuple entityTuple;
private final TransactionContext transactionContext;

public AssociationContextImpl(AssociationTypeContext associationTypeContext, Tuple entityTuple) {
this( associationTypeContext, entityTuple, null );
public AssociationContextImpl(AssociationTypeContext associationTypeContext, Tuple entityTuple, TransactionContext transactionContext) {
this( associationTypeContext, entityTuple, null, transactionContext );
}

public AssociationContextImpl(AssociationContextImpl original, OperationsQueue operationsQueue) {
this( original.associationTypeContext, original.entityTuple, operationsQueue );
this( original.associationTypeContext, original.entityTuple, operationsQueue, original.transactionContext );
}

private AssociationContextImpl(AssociationTypeContext associationTypeContext, Tuple entityTuple, OperationsQueue operationsQueue) {
private AssociationContextImpl(AssociationTypeContext associationTypeContext,
Tuple entityTuple,
OperationsQueue operationsQueue,
TransactionContext transactionContext) {
Contracts.assertParameterNotNull( associationTypeContext, "associationTypeContext" );

this.associationTypeContext = associationTypeContext;
this.entityTuple = entityTuple;
this.operationsQueue = operationsQueue;
this.transactionContext = transactionContext;
}

@Override
Expand All @@ -52,6 +58,11 @@ public OperationsQueue getOperationsQueue() {
return operationsQueue;
}

@Override
public TransactionContext getTransactionContext() {
return transactionContext;
}

@Override
public Tuple getEntityTuple() {
return entityTuple;
Expand Down
Expand Up @@ -181,13 +181,13 @@ public void executeBatch(OperationsQueue queue) {
*/

@Override
public ClosableIterator<Tuple> executeBackendQuery(BackendQuery<T> query, QueryParameters queryParameters) {
return queryableGridDialect.executeBackendQuery( query, queryParameters );
public ClosableIterator<Tuple> executeBackendQuery(BackendQuery<T> query, QueryParameters queryParameters, TupleContext tupleContext) {
return queryableGridDialect.executeBackendQuery( query, queryParameters, tupleContext );
}

@Override
public int executeBackendUpdateQuery(BackendQuery<T> query, QueryParameters queryParameters) {
return queryableGridDialect.executeBackendUpdateQuery( query, queryParameters );
public int executeBackendUpdateQuery(BackendQuery<T> query, QueryParameters queryParameters, TupleContext tupleContext) {
return queryableGridDialect.executeBackendUpdateQuery( query, queryParameters, tupleContext );
}

@Override
Expand Down
Expand Up @@ -139,8 +139,8 @@ public void executeBatch(OperationsQueue queue) {
}

@Override
public ClosableIterator<Tuple> executeBackendQuery(BackendQuery<Serializable> query, QueryParameters queryParameters) {
public ClosableIterator<Tuple> executeBackendQuery(BackendQuery<Serializable> query, QueryParameters queryParameters, TupleContext tupleContext) {
log.tracef( "Executing backend query: %1$s", query.getQuery() );
return super.executeBackendQuery( query, queryParameters );
return super.executeBackendQuery( query, queryParameters, tupleContext );
}
}
Expand Up @@ -11,6 +11,7 @@
import java.util.Map;

import org.hibernate.ogm.dialect.batch.spi.OperationsQueue;
import org.hibernate.ogm.dialect.spi.TransactionContext;
import org.hibernate.ogm.dialect.spi.TupleContext;
import org.hibernate.ogm.model.key.spi.AssociatedEntityKeyMetadata;
import org.hibernate.ogm.options.spi.OptionsContext;
Expand All @@ -27,6 +28,7 @@ public class TupleContextImpl implements TupleContext {
private final List<String> selectableColumns;
private final OptionsContext optionsContext;
private final OperationsQueue operationsQueue;
private final TransactionContext transactionContext;

/**
* Information of the associated entity stored per foreign key column names
Expand All @@ -36,19 +38,30 @@ public class TupleContextImpl implements TupleContext {
private final Map<String, String> roles;

public TupleContextImpl(TupleContextImpl original, OperationsQueue operationsQueue) {
this( original.selectableColumns, original.associatedEntityMetadata, original.roles, original.optionsContext, operationsQueue );
this( original.selectableColumns, original.associatedEntityMetadata, original.roles, original.optionsContext, operationsQueue, original.transactionContext );
}

public TupleContextImpl(List<String> selectableColumns, Map<String, AssociatedEntityKeyMetadata> associatedEntityMetadata, Map<String, String> roles, OptionsContext optionsContext) {
this( selectableColumns, associatedEntityMetadata, roles, optionsContext, null );
public TupleContextImpl(TupleContextImpl original, TransactionContext transactionContext) {
this( original.selectableColumns, original.associatedEntityMetadata, original.roles, original.optionsContext, original.operationsQueue, transactionContext );
}

private TupleContextImpl(List<String> selectableColumns, Map<String, AssociatedEntityKeyMetadata> associatedEntityMetadata, Map<String, String> roles, OptionsContext optionsContext, OperationsQueue operationsQueue) {
public TupleContextImpl(List<String> selectableColumns, Map<String, AssociatedEntityKeyMetadata> associatedEntityMetadata, Map<String, String> roles, OptionsContext optionsContext, TransactionContext transactionContext) {
this( selectableColumns, associatedEntityMetadata, roles, optionsContext, null, transactionContext );
}

private TupleContextImpl(List<String> selectableColumns,
Map<String, AssociatedEntityKeyMetadata> associatedEntityMetadata,
Map<String, String> roles,
OptionsContext optionsContext,
OperationsQueue operationsQueue,
TransactionContext transactionContext) {

this.selectableColumns = selectableColumns;
this.associatedEntityMetadata = Collections.unmodifiableMap( associatedEntityMetadata );
this.roles = Collections.unmodifiableMap( roles );
this.optionsContext = optionsContext;
this.operationsQueue = operationsQueue;
this.transactionContext = transactionContext;
}

@Override
Expand All @@ -61,6 +74,11 @@ public OptionsContext getOptionsContext() {
return optionsContext;
}

@Override
public TransactionContext getTransactionContext() {
return transactionContext;
}

@Override
public boolean isPartOfAssociation(String column) {
return associatedEntityMetadata.containsKey( column );
Expand Down
Expand Up @@ -11,7 +11,7 @@

/**
* Represents a NoSQL query as to be executed via
* {@link QueryableGridDialect#executeBackendQuery(BackendQuery, QueryParameters)}.
* {@link QueryableGridDialect#executeBackendQuery(BackendQuery, QueryParameters, TupleContext)}
* <p>
* The wrapped query object generally represents the query in the native form supported by a given datastore, e.g. a
* String in a native query syntax or an object-based query representation such as the {@code DBObject}-based query
Expand Down
Expand Up @@ -12,6 +12,7 @@
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.ogm.type.spi.TypeTranslator;

Expand All @@ -33,14 +34,14 @@ public QueryParameters(RowSelection rowSelection, Map<String, TypedGridValue> na
this.positionalParameters = positionalParameters;
}

public static QueryParameters fromOrmQueryParameters(org.hibernate.engine.spi.QueryParameters parameters, TypeTranslator typeTranslator) {
public static QueryParameters fromOrmQueryParameters(org.hibernate.engine.spi.QueryParameters parameters, TypeTranslator typeTranslator, SessionFactoryImplementor sessionFactoryImplementor) {
RowSelection selection = RowSelection.fromOrmRowSelection( parameters.getRowSelection() );
Map<String, TypedGridValue> namedParameters = new HashMap<>();

for ( Entry<String, TypedValue> parameter : parameters.getNamedParameters().entrySet() ) {
namedParameters.put( parameter.getKey(), TypedGridValue.fromOrmTypedValue( parameter.getValue(), typeTranslator ) );
}
Map<String, TypedGridValue> namedParameters = createNamedParameters( sessionFactoryImplementor, parameters, typeTranslator );
List<TypedGridValue> positionalParameters = createPositionalParameters( parameters, typeTranslator );
return new QueryParameters( selection, namedParameters, positionalParameters);
}

private static List<TypedGridValue> createPositionalParameters(org.hibernate.engine.spi.QueryParameters parameters, TypeTranslator typeTranslator) {
List<TypedGridValue> positionalParameters = new ArrayList<>( parameters.getPositionalParameterTypes().length );
for ( int i = 0; i < parameters.getPositionalParameterTypes().length; i++) {
positionalParameters.add(
Expand All @@ -50,7 +51,16 @@ public static QueryParameters fromOrmQueryParameters(org.hibernate.engine.spi.Qu
)
);
}
return new QueryParameters( selection, namedParameters, positionalParameters );
return positionalParameters;
}

private static Map<String, TypedGridValue> createNamedParameters(SessionFactoryImplementor factory, org.hibernate.engine.spi.QueryParameters parameters, TypeTranslator typeTranslator) {
Map<String, TypedGridValue> namedParameters = new HashMap<>();
for ( Entry<String, TypedValue> parameter : parameters.getNamedParameters().entrySet() ) {
TypedGridValue typedGridValue = TypedGridValue.fromOrmTypedValue( parameter.getValue(), typeTranslator, factory );
namedParameters.put( parameter.getKey(), typedGridValue );
}
return namedParameters;
}

public RowSelection getRowSelection() {
Expand Down
Expand Up @@ -9,6 +9,7 @@
import java.io.Serializable;

import org.hibernate.ogm.dialect.spi.GridDialect;
import org.hibernate.ogm.dialect.spi.TupleContext;
import org.hibernate.ogm.model.spi.Tuple;

/**
Expand All @@ -27,9 +28,10 @@ public interface QueryableGridDialect<T extends Serializable> extends GridDialec
* @param query the query to execute in a representation understood by the underlying datastore. May have been
* created by converting a JP-QL query or from a (named) native query.
* @param queryParameters parameters passed for this query
* @param tupleContext the tuple context
* @return an {@link ClosableIterator} with the result of the query
*/
ClosableIterator<Tuple> executeBackendQuery(BackendQuery<T> query, QueryParameters queryParameters);
ClosableIterator<Tuple> executeBackendQuery(BackendQuery<T> query, QueryParameters queryParameters, TupleContext tupleContext);

/**
* Returns the result of a native update query executed on the backend.
Expand All @@ -43,9 +45,10 @@ public interface QueryableGridDialect<T extends Serializable> extends GridDialec
* @param query the query to execute in a representation understood by the underlying datastore. May have been
* created by converting a JP-QL query or from a (named) native query.
* @param queryParameters parameters passed for this query
* @param tupleContext the tuple context
* @return the number of elements that have been updated.
*/
int executeBackendUpdateQuery(BackendQuery<T> query, QueryParameters queryParameters);
int executeBackendUpdateQuery(BackendQuery<T> query, QueryParameters queryParameters, TupleContext tupleContext);

/**
* Returns a builder for retrieving parameter meta-data from native queries in this datastore's format.
Expand Down
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.ogm.dialect.query.spi;

import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.ogm.type.spi.GridType;
import org.hibernate.ogm.type.spi.TypeTranslator;
Expand All @@ -26,9 +27,10 @@ public TypedGridValue(GridType type, Object value) {
this.value = value;
}

public static TypedGridValue fromOrmTypedValue(TypedValue typedValue, TypeTranslator typeTranslator) {
public static TypedGridValue fromOrmTypedValue(TypedValue typedValue, TypeTranslator typeTranslator, SessionFactoryImplementor factory) {
GridType gridType = typeTranslator.getType( typedValue.getType() );
return new TypedGridValue( gridType, typedValue.getValue() );
Object backendValue = gridType.convertToBackendType( typedValue.getValue(), factory );
return new TypedGridValue( gridType, backendValue );
}

public GridType getType() {
Expand Down
Expand Up @@ -40,4 +40,11 @@ public interface AssociationContext {
* @return A tuple representing the entity on the current side of the association
*/
Tuple getEntityTuple();

/**
* Provides the information related to the transactional boundaries the query can be executed
*
* @return a transaction context containing information about the current running transaction, or null
*/
TransactionContext getTransactionContext();
}
Expand Up @@ -28,6 +28,13 @@ public interface TupleContext {
*/
OptionsContext getOptionsContext();

/**
* Provides the information related to the transactional boundaries the query can be executed
*
* @return a transaction context containing information about the current running transaction, or null
*/
TransactionContext getTransactionContext();

/**
* Returns the mapped columns of the given entity. May be used by a dialect to only load those columns instead of
* the complete document/record. If the dialect supports the embedded storage of element collections and
Expand Down
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.ogm.hibernatecore.impl;

import static org.hibernate.ogm.util.impl.TupleContextHelper.tupleContext;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
Expand All @@ -25,6 +27,7 @@
import org.hibernate.ogm.dialect.query.spi.ClosableIterator;
import org.hibernate.ogm.dialect.query.spi.QueryParameters;
import org.hibernate.ogm.dialect.query.spi.QueryableGridDialect;
import org.hibernate.ogm.dialect.spi.TupleContext;
import org.hibernate.ogm.loader.impl.OgmLoadingContext;
import org.hibernate.ogm.loader.impl.TupleBasedEntityLoader;
import org.hibernate.ogm.loader.nativeloader.impl.BackendCustomQuery;
Expand Down Expand Up @@ -83,7 +86,7 @@ private boolean isEntityQuery() {

@Override
protected List<?> list(SessionImplementor session, org.hibernate.engine.spi.QueryParameters queryParameters, Set querySpaces, Type[] resultTypes) throws HibernateException {
ClosableIterator<Tuple> tuples = loaderContext.executeQuery( QueryParameters.fromOrmQueryParameters( queryParameters, typeTranslator ) );
ClosableIterator<Tuple> tuples = loaderContext.executeQuery( session, QueryParameters.fromOrmQueryParameters( queryParameters, typeTranslator, session.getFactory() ) );
try {
if ( isEntityQuery() ) {
return listOfEntities( session, resultTypes, tuples );
Expand Down Expand Up @@ -171,19 +174,20 @@ private TupleBasedEntityLoader getLoader(SessionImplementor session, Class<?> en
* @author Gunnar Morling
*/
private static class BackendCustomLoaderContext<T extends Serializable> {

private final QueryableGridDialect<T> gridDialect;
private final BackendQuery<T> query;

public BackendCustomLoaderContext(QueryableGridDialect<T> gridDialect, BackendCustomQuery<T> customQuery) {
this.gridDialect = gridDialect;
this.query = new BackendQuery<T>(
customQuery.getQueryObject(),
customQuery.getSingleEntityMetadataInformationOrNull()
);
customQuery.getSingleEntityMetadataInformationOrNull() );
}

public ClosableIterator<Tuple> executeQuery(QueryParameters queryParameters) {
return gridDialect.executeBackendQuery( query, queryParameters );
public ClosableIterator<Tuple> executeQuery(SessionImplementor session, QueryParameters queryParameters) {
TupleContext tupleContext = tupleContext( session, query.getSingleEntityMetadataInformationOrNull() );
return gridDialect.executeBackendQuery( query, queryParameters, tupleContext );
}
}
}
Expand Up @@ -568,15 +568,15 @@ private TupleAsMapResultSet getResultSet(Serializable id, QueryParameters qp, Og
keys[index] = EntityKeyBuilder.fromPersister( persister, (Serializable) qp.getPositionalParameterValues()[index], session );
}
if ( multigetGridDialect != null ) {
for ( Tuple tuple : multigetGridDialect.getTuples( keys, persister.getTupleContext() ) ) {
for ( Tuple tuple : multigetGridDialect.getTuples( keys, persister.getTupleContext( session ) ) ) {
if ( tuple != null ) {
resultset.addTuple( tuple );
}
}
}
else {
for ( EntityKey entityKey : keys ) {
Tuple entry = gridDialect.getTuple( entityKey, persister.getTupleContext() );
Tuple entry = gridDialect.getTuple( entityKey, persister.getTupleContext( session ) );
if ( entry != null ) {
resultset.addTuple( entry );
}
Expand All @@ -585,7 +585,7 @@ private TupleAsMapResultSet getResultSet(Serializable id, QueryParameters qp, Og
}
else {
final EntityKey key = EntityKeyBuilder.fromPersister( persister, id, session );
Tuple entry = gridDialect.getTuple( key, persister.getTupleContext() );
Tuple entry = gridDialect.getTuple( key, persister.getTupleContext( session ) );
if ( entry != null ) {
resultset.addTuple( entry );
}
Expand Down
Expand Up @@ -74,7 +74,7 @@ public void run() {
final EntityKeyMetadata keyMetadata = new DefaultEntityKeyMetadata( persister.getTableName(), persister.getRootTableIdentifierColumnNames() );

final SessionAwareRunnable consumer = new TupleIndexer( indexedType, monitor, sessionFactory, searchIntegrator, cacheMode, batchBackend, errorHandler, tenantId );
gridDialect.forEachTuple( new OptionallyWrapInJTATransaction( sessionFactory, errorHandler, consumer ), persister.getTupleContext(), keyMetadata );
gridDialect.forEachTuple( new OptionallyWrapInJTATransaction( sessionFactory, errorHandler, consumer ), persister.getTupleContext( null ), keyMetadata );
}
catch ( RuntimeException re ) {
// being this an async thread we want to make sure everything is somehow reported
Expand Down

0 comments on commit 1779831

Please sign in to comment.