Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Hibernate OGM, Domain model persistence for NoSQL datastores
   *
   * License: GNU Lesser General Public License (LGPL), version 2.1 or later
   * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
   */
  package org.hibernate.ogm.persister.impl;
  
 import java.util.Set;
 
CollectionPersister storing the collection in a grid

Author(s):
Emmanuel Bernard
 
 
 	private static final Log log = LoggerFactory.make();
 
 	private final GridType keyGridType;
 	private final GridType elementGridType;
 	private final GridType indexGridType;
 	private final GridType identifierGridType;
 	private final boolean isInverse;
 	private final boolean oneToMany;
 	private final GridType gridTypeOfAssociatedId;
 	private final AssociationType associationType;
 	private final GridDialect gridDialect;
 
 	private final String nodeName;

The OgmCollectionPersister from the other side of this association in case it represents the main side of a bi-directional many-to-many association, null otherwise.
 
The name of the main side property in case this is the inverse side of a one-to-many or many-to-many association.
 
A context to be passed (either directly or via org.hibernate.ogm.dialect.spi.AssociationContext) to grid dialect operations relating to the association managed by this persister.
	public OgmCollectionPersister(final Collection collectionfinal CollectionRegionAccessStrategy cacheAccessStrategyfinal Configuration cfgfinal SessionFactoryImplementor factory)
		supercollectioncacheAccessStrategycfgfactory );
		ServiceRegistry registry = factory.getServiceRegistry();
		final TypeTranslator typeTranslator = registry.getServiceTypeTranslator.class );
		this. = registry.getServiceGridDialect.class );
		 = typeTranslator.getTypegetKeyType() );
		 = typeTranslator.getTypegetElementType() );
		 = typeTranslator.getTypegetIndexType() );
		 = typeTranslator.getTypegetIdentifierType() );
		// copied from the superclass constructor
		 = collection.isInverse();
		 = collection.isOneToMany();
		if ( collection.isOneToMany() && getElementPersister() != null && getElementType().isEntityType() ) {
			final Type identifierOrUniqueKeyType = ( (EntityTypegetElementType() )
			 = typeTranslator.getTypeidentifierOrUniqueKeyType );
		}
		else if ( collection.isOneToMany() ) {
			// one to many but not what we expected
			throw new AssertionFailure"Association marked as one to many but has no ManyToOneType: " + collection.getRole() );
		}
			final Type identifierOrUniqueKeyType = ( (EntityTypegetElementType() ).getIdentifierOrUniqueKeyTypefactory );
			 = typeTranslator.getTypeidentifierOrUniqueKeyType );
		}
		else {
		}
		String[] rowKeyColumnNames = rowKeyBuilder.getColumnNames();
		String[] rowKeyIndexColumnNames = rowKeyBuilder.getIndexColumnNames();
				.rowKeyColumnNamesrowKeyColumnNames )
				.rowKeyIndexColumnNamesrowKeyIndexColumnNames )
				.oneToOnefalse )
		 = collection.getNodeName();
	}
		String role = getRole();
		return role.substringentity.length() + 1 );
	}
	private EntityKeyMetadata targetEntityKeyMetadataboolean inverse ) {
		if ( inverse ) {
			// Bidirectional *ToMany
		}
		else if ( getElementType().isEntityType() ) {
			// *ToMany
		}
		else {
			// Embedded we need to build the key metadata
			String[] targetColumnNames = null;
			if ( inverse ) {
				targetColumnNames = getKeyColumnNames();
			}
			else {
				targetColumnNames = getElementColumnNames();
			}
			return new DefaultEntityKeyMetadatagetTableName(), targetColumnNames );
		}
	}
	}

represents the type of associations at stake
	private enum AssociationType {

OneToMany:
@JoinColumn
		EMBEDDED_FK_TO_ENTITY,

ManyToMany:
@JoinTable
		ASSOCIATION_TABLE_TO_ENTITY,
collection of Embeddable
		OTHER
	}
	public Object readKey(ResultSet rsString[] aliasesSessionImplementor session)
		final TupleAsMapResultSet resultset = rs.unwrapTupleAsMapResultSet.class );
		final Tuple keyTuple = resultset.getTuple();
		return .nullSafeGetkeyTuplealiasessessionnull );
	}
	public Object readElement(ResultSet rsObject ownerString[] aliasesSessionImplementor session)
		final TupleAsMapResultSet resultset = rs.unwrapTupleAsMapResultSet.class );
		final Tuple keyTuple = resultset.getTuple();
		return .nullSafeGetkeyTuplealiasessessionowner );
	}
	public Object readIdentifier(ResultSet rsString aliasSessionImplementor session)
		final TupleAsMapResultSet resultset = rs.unwrapTupleAsMapResultSet.class );
		final Tuple keyTuple = resultset.getTuple();
		return .nullSafeGetkeyTuplealiassessionnull );
	}
	public Object readIndex(ResultSet rsString[] aliasesSessionImplementor session)
		final TupleAsMapResultSet resultset = rs.unwrapTupleAsMapResultSet.class );
		final Tuple keyTuple = resultset.getTuple();
		return .nullSafeGetkeyTuplealiasessessionnull );
	}
		return null;
	}
		// TODO pass constructor
		return new OgmBasicCollectionLoaderthis );
	}
		return ;
	}
	}
	public boolean isOneToMany() {
		return ;
	}
	public boolean isManyToMany() {
		// Let's see if we can model everything like that. That'd be nice
		return true;
	}
	public boolean isCascadeDeleteEnabled() {
		// TODO always false: OGM does not assume cascade delete is supported by the underlying engine
		return false;
	}
		return null;
	}
		return null;
	}
		return null;
	}
		return null;
	}
	protected int doUpdateRows(Serializable keyPersistentCollection collectionSessionImplementor session)
		if ( ArrayHelper.isAllFalse ) ) {
			return 0;
		}
		int count = 0;
		int i = 0;
		Iterator<?> entries = collection.entriesthis );
		AssociationPersister associationPersister = getAssociationPersistercollection.getOwner(), keysession );
		while ( entries.hasNext() ) {
			Object entry = entries.next();
			if ( collection.needsUpdatingentryi ) ) {
				// find the matching element
				RowKey assocEntryKey = getTupleKeyForUpdatekeycollectionsessionientryassociationPersister );
				Tuple assocEntryTuple = associationPersister.getAssociation().getassocEntryKey );
				if ( assocEntryTuple == null ) {
					throw new AssertionFailure"Updating a collection tuple that is not present: " + "table {" + getTableName() + "} collectionKey {" + key + "} entry {" + entry + "}" );
				}
				// update the matching element
				// FIXME update the associated entity key data
				updateInverseSideOfAssociationNavigationsessionentryassociationPersister.getAssociationKey(), assocEntryTuple.assocEntryKey );
						assocEntryTuple,
						collection.getElemententry ),
						session
				);
				// put back entry tuple to actually apply changes to the store
				associationPersister.getAssociation().putassocEntryKeyassocEntryTuple );
				updateInverseSideOfAssociationNavigationsessionentryassociationPersister.getAssociationKey(), assocEntryTuple.assocEntryKey );
				count++;
			}
			i++;
		}
		// need to put the data back in the cache
		associationPersister.flushToDatastore();
		return count;
	}

Creates an association row representing the given entry and adds it to the association managed by the given persister.
			AssociationPersister associationPersisterSessionImplementor sessionint iObject entry) {
		Tuple associationRow = new Tuple();
		// the collection has a surrogate key (see @CollectionId)
		if (  ) {
			final Object identifier = collection.getIdentifierentryi );
			String[] names = { getIdentifierColumnName() };
			.nullSafeSetassociationRowidentifiernamessession );
		}
		getKeyGridType().nullSafeSetassociationRowkeygetKeyColumnNames(), session );
		// No need to write to where as we don't do where clauses in OGM :)
		if (  ) {
			Object index = collection.getIndexentryithis );
			.nullSafeSetassociationRowincrementIndexByBaseindex ), getIndexColumnNames(), session );
		}
		// columns of referenced key
		final Object element = collection.getElemententry );
		getElementGridType().nullSafeSetassociationRowelementgetElementColumnNames(), session );
		RowKeyAndTuple result = new RowKeyAndTuple();
		result.key = rowKeyBuilder.valuesassociationRow ).build();
		result.tuple = associationRow;
		associationPersister.getAssociation().putresult.keyresult.tuple );
		return result;
	}
	private static class RowKeyAndTuple {
	}
	// Centralize the RowKey column setting logic as the values settings are slightly different between insert / update and delete
		RowKeyBuilder builder = new RowKeyBuilder();
		if (  ) {
		}
		else {
			// !isOneToMany() present in delete not in update
			if ( !isOneToMany() &&  && ! ) {
			}
			else {
			}
		}
		return builder;
	}
	private RowKey getTupleKeyForUpdate(Serializable keyPersistentCollection collectionSessionImplementor sessionint iObject entryAssociationPersister associationPersister) {
		Tuple tuple = new Tuple();
		if (  ) {
			final Object identifier = collection.getIdentifierentryi );
			String[] names = { getIdentifierColumnName() };
			.nullSafeSettupleidentifiernamessession );
		}
		else {
			getKeyGridType().nullSafeSettuplekeygetKeyColumnNames(), session );
			// No need to write to where as we don't do where clauses in OGM :)
			if ( !isOneToMany() &&  && ! ) {
				Object index = collection.getIndexentryithis );
			}
			else {
				final Object snapshotElement = collection.getSnapshotElemententryi );
					throw new AssertionFailure"cannot use a formula-based element in the where condition" );
				}
				getElementGridType().nullSafeSettuplesnapshotElementgetElementColumnNames(), session );
			}
		}
		rowKeyBuilder.valuestuple );
		return rowKeyBuilder.build();
	}
	private RowKey getTupleKeyForDelete(Serializable keyPersistentCollection collectionSessionImplementor sessionObject entryboolean findByIndexAssociationPersister associationPersister) {
		Tuple tuple = new Tuple();
		if (  ) {
			final Object identifier = entry;
			String[] names = { getIdentifierColumnName() };
			.nullSafeSettupleidentifiernamessession );
		}
		else {
			getKeyGridType().nullSafeSettuplekeygetKeyColumnNames(), session );
			// No need to write to where as we don't do where clauses in OGM :)
			if ( findByIndex ) {
				Object index = entry;
			}
			else {
				final Object snapshotElement = entry;
					throw new AssertionFailure"cannot use a formula-based element in the where condition" );
				}
				getElementGridType().nullSafeSettuplesnapshotElementgetElementColumnNames(), session );
			}
		}
		rowKeyBuilder.valuestuple );
		return rowKeyBuilder.build();
	}
	public int getSize(Serializable keySessionImplementor session) {
		AssociationPersister associationPersister = getAssociationPersistersession.getPersistenceContext().getEntitynew org.hibernate.engine.spi.EntityKeykeygetOwnerEntityPersister() ) ), keysession );
		final Association collectionMetadata = associationPersister.getAssociationOrNull();
		return collectionMetadata == null ? 0 : collectionMetadata.size();
	}
		return new StaticFilterAliasGeneratorrootAlias );
	}
	public void deleteRows(PersistentCollection collectionSerializable idSessionImplementor session)
		if ( ! && isRowDeleteEnabled() ) {
			if ( .isDebugEnabled() ) {
				.debug"Deleting rows of collection: " + MessageHelper.collectionInfoStringthisidgetFactory() ) );
			}
			boolean deleteByIndex = !isOneToMany() &&  && !;
			AssociationPersister associationPersister = getAssociationPersistercollection.getOwner(), idsession );
			// delete all the deleted entries
			Iterator<?> deletes = collection.getDeletesthis, !deleteByIndex );
			if ( deletes.hasNext() ) {
				int count = 0;
				while ( deletes.hasNext() ) {
					Object entry = deletes.next();
					// find the matching element
					RowKey assocEntryKey = getTupleKeyForDeleteidcollectionsessionentrydeleteByIndexassociationPersister );
					Tuple assocEntryTuple = associationPersister.getAssociation().getassocEntryKey );
					if ( assocEntryTuple == null ) {
						throw new AssertionFailure"Deleting a collection tuple that is not present: " + "table {" + getTableName() + "} collectionKey {" + id + "} entry {" + entry + "}" );
					}
					// delete the tuple
					updateInverseSideOfAssociationNavigationsessionentryassociationPersister.getAssociationKey(), assocEntryTuple.assocEntryKey );
					associationPersister.getAssociation().removeassocEntryKey );
					count++;
				}
				associationPersister.flushToDatastore();
				if ( .isDebugEnabled() ) {
					.debug"done deleting collection rows: " + count + " deleted" );
				}
			}
			else {
				.debug"no rows to delete" );
			}
		}
	}
	public void insertRows(PersistentCollection collectionSerializable idSessionImplementor session)
		if ( ! && isRowInsertEnabled() ) {
			if ( .isDebugEnabled() ) {
				.debug"Inserting rows of collection: " + MessageHelper.collectionInfoStringthisidgetFactory() ) );
			}
			AssociationPersister associationPersister = getAssociationPersistercollection.getOwner(), idsession );
			// insert all the new entries
			collection.preInsertthis );
			Iterator<?> entries = collection.entriesthis );
			int i = 0;
			int count = 0;
			while ( entries.hasNext() ) {
				Object entry = entries.next();
				if ( collection.needsInsertingentryi ) ) {
					// TODO: copy/paste from recreate()
					RowKeyAndTuple associationRow = createAndPutAssociationRowForInsertidcollectionassociationPersistersessionientry );
					updateInverseSideOfAssociationNavigationsessionentryassociationPersister.getAssociationKey(), associationRow.tuple.associationRow.key );
					collection.afterRowInsertthisentryi );
					count++;
				}
				i++;
			}
			associationPersister.flushToDatastore();
			if ( .isDebugEnabled() ) {
				.debug"done inserting rows: " + count + " inserted" );
			}
		}
	}
	public void recreate(PersistentCollection collectionSerializable idSessionImplementor session)
		if ( ! && isRowInsertEnabled() ) {
			if ( .isDebugEnabled() ) {
				.debug"Inserting collection: " + MessageHelper.collectionInfoStringthisidgetFactory() ) );
			}
			AssociationPersister associationPersister = getAssociationPersistercollection.getOwner(), idsession );
			// create all the new entries
			Iterator<?> entries = collection.entriesthis );
			if ( entries.hasNext() ) {
				collection.preInsertthis );
				int i = 0;
				int count = 0;
				while ( entries.hasNext() ) {
					final Object entry = entries.next();
					if ( collection.entryExistsentryi ) ) {
						// TODO: copy/paste from insertRows()
						RowKeyAndTuple keyAndTuple = createAndPutAssociationRowForInsertidcollectionassociationPersistersessionientry );
						updateInverseSideOfAssociationNavigationsessionentryassociationPersister.getAssociationKey(), keyAndTuple.tuple.keyAndTuple.key );
						collection.afterRowInsertthisentryi );
						count++;
					}
					i++;
				}
				associationPersister.flushToDatastore();
				if ( .isDebugEnabled() ) {
					.debug"done inserting collection: " + count + " rows inserted" );
				}
			}
			else {
				if ( .isDebugEnabled() ) {
					.debug"collection was empty" );
				}
			}
		}
	}
	private void updateInverseSideOfAssociationNavigation(SessionImplementor sessionObject entityAssociationKey associationKeyTuple associationRowAction actionRowKey rowKey) {
			// update the associated object
			Serializable entityId = (Serializable.nullSafeGetassociationRowgetElementColumnNames(), sessionnull );
			final EntityKey entityKey = EntityKeyBuilder.fromPersisterpersisterentityIdsession );
			final Tuple entityTuple = .getTupleentityKeypersister.getTupleContext() );
			// the entity tuple could already be gone (not 100% sure this can happen but that feels right)
			if ( entityTuple == null ) {
				return;
			}
			if ( action == . ) {
				for ( String columnName : associationKey.getColumnNames() ) {
					entityTuple.putcolumnNameassociationRow.getcolumnName ) );
				}
			}
			else if ( action == . ) {
				if (  ) {
					throw new AssertionFailure"A true OneToMany with an identifier for the collection: " + getRole() );
				}
				.nullSafeSetentityTuplenullgetKeyColumnNames(), session );
			}
			else {
				throw new AssertionFailure"Unknown action type: " + action );
			}
			.insertOrUpdateTupleentityKeyentityTuplepersister.getTupleContext() );
		}
			String[] elementColumnNames = getElementColumnNames();
			Object[] elementColumnValues = LogicalPhysicalConverterHelper.getColumnValuesFromResultsetassociationRowelementColumnNames );
			Serializable entityId = (Serializable.nullSafeGetassociationRowgetElementColumnNames(), sessionnull );
			if (  == null ) {
				return;
			}
			if ( entity == null ) {
				entity = session.getPersistenceContext().getEntitysession.generateEntityKeyentityIdgetElementPersister() ) );
			}
			AssociationPersister associationPersister = .getAssociationPersisterentityelementColumnValuessession );
			// TODO what happens when a row should be *updated* ?: I suspect ADD works OK as it's a put()
			if ( action == . ) {
				RowKey inverseRowKey = getInverseRowKeyassociationRow );
				Tuple inverseAssociationRow = new Tuple();
				associationPersister.getAssociation().putinverseRowKeyinverseAssociationRow );
				for ( String columnName : inverseRowKey.getColumnNames() ) {
					inverseAssociationRow.putcolumnNameassociationRow.getcolumnName ) );
				}
				associationPersister.getAssociation().putinverseRowKeyinverseAssociationRow );
			}
			else if ( action == . ) {
				// we try and match the whole tuple as it should be on both sides of the navigation
				if ( rowKey == null ) {
					throw new AssertionFailure"Deleting a collection tuple that is not present: " + "table {"
getTableName() + "} key column names {" + Arrays.toStringelementColumnNames )
"} key column values {" + Arrays.toStringelementColumnValues ) + "}" );
				}
				RowKey inverseRowKey = getInverseRowKeyassociationRow );
				associationPersister.getAssociation().removeinverseRowKey );
			}
			else {
				throw new AssertionFailure"Unknown action type: " + action );
			}
			associationPersister.flushToDatastore();
		}
	}
	private RowKey getInverseRowKey(Tuple associationRow) {
		Object[] columnValues = new Object[inverseRowKeyColumnNames.length];
		for ( int i = 0; i < inverseRowKeyColumnNames.lengthi++ ) {
			columnValues[i] = associationRow.getinverseRowKeyColumnNames[i] );
		}
		return new RowKeyinverseRowKeyColumnNamescolumnValues );
	}
	private static enum Action {
		ADD, REMOVE
	}
	public void remove(Serializable idSessionImplementor sessionthrows HibernateException {
		if ( ! && isRowDeleteEnabled() ) {
			if ( .isDebugEnabled() ) {
				.debug"Deleting collection: " + MessageHelper.collectionInfoStringthisidgetFactory() ) );
			}
			Object owner = session.getPersistenceContext().getCollectionOwneridthis );
			// Remove all the old entries
			AssociationPersister associationPersister = getAssociationPersisterowneridsession );
			Association association = associationPersister.getAssociationOrNull();
			if ( association != null ) {
				// shortcut to avoid loop if we can
					for ( RowKey assocEntryKey : association.getKeys() ) {
						// we unfortunately cannot mass change the update of the associated entity
								session,
								null,
								associationPersister.getAssociationKey(),
								association.getassocEntryKey ),
								assocEntryKey
								);
					}
				}
				association.clear();
				associationPersister.flushToDatastore();
			}
			if ( .isDebugEnabled() ) {
				.debug"done deleting collection" );
			}
		}
	}
	public String selectFragment(Joinable rhsString rhsAliasString lhsAliasString currentEntitySuffixString currentCollectionSuffixboolean includeCollectionColumns) {
		return null;
	}
	public String whereJoinFragment(String aliasboolean innerJoinboolean includeSubclasses) {
		return null;
	}
	public String fromJoinFragment(String aliasboolean innerJoinboolean includeSubclasses) {
		return null;
	}
	public boolean consumesEntityAlias() {
		return false;
	}
	public boolean consumesCollectionAlias() {
		return false// To change body of implemented methods use File | Settings | File Templates.
	}
	protected void logStaticSQL() {
		if ( .isDebugEnabled() ) {
			.debug"No SQL used when using OGM: " + getRole() );
		}
	}
	public void postInstantiate() throws MappingException {
		if (  ) {
			 = BiDirectionalAssociationHelper.getMainSidePropertyNamethis );
		}
		else {
			 = BiDirectionalAssociationHelper.getInverseCollectionPersisterthis );
		}
	}
		// we have no query loader
		// we don't handle subselect
		// we don't know how to support filters on OGM today
	}
	protected void doProcessQueuedOps(PersistentCollection collectionSerializable keySessionImplementor sessionthrows HibernateException {
		// nothing to do
	}
	// NOTE: This method has accidentally been introduced in ORM 4.3.5 and is deprecated as of ORM 4.3.6. We're
	// overriding this variant and the one above to be compatible with any 4.3.x version. This variant can be removed
	// once we're on ORM 5
	protected void doProcessQueuedOps(PersistentCollection collectionSerializable keyint nextIndexSessionImplementor sessionthrows HibernateException {
		// nothing to do
	}
	public String whereJoinFragment(String aliasboolean innerJoinboolean includeSubclassesSet<StringtreatAsDeclarations) {
		return null;
	}
	public String fromJoinFragment(String aliasboolean innerJoinboolean includeSubclassesSet<StringtreatAsDeclarations) {
		return null;
	}

Get the property name representing the collection on the main side of the association.

Returns:
the property name on the main side, if this collection represents the inverse (non-main) side of a bi-directional association, this association's own property name otherwise.
	}

Returns the association type context providing meta-data to be passed to grid dialects when working on this association.

Note: Due to initialization order related constraints, this method may only be invoked after all collection and entity persisters have been set up. Use getAssociationTypeContext(java.lang.String) when in need of a context prior to that point.

Returns:
the association type context, it never returns null
		Contracts.assertNotNull"Association type context has not yet been initialized" );
	}
	public AssociationTypeContext getAssociationTypeContext(String mainSidePropertyName) {
		OptionsServiceContext serviceContext = getFactory()
		AssociationTypeContext associationTypeContext = new AssociationTypeContextImpl(
				mainSidePropertyName
		);
		return associationTypeContext;
	}
			)
			.hostingEntitycollectionOwner )
			.keyidgetKeyGridType() )
			.sessionsession );
	}
	private AssociationPersister getAssociationPersister(Object collectionOwnerObject[] keyColumnValuesSessionImplementor session) {
			)
			.hostingEntitycollectionOwner )
			.keyColumnValueskeyColumnValues )
			.sessionsession );
	}