hibernate/hibernate-orm · error · HibernateException

Found two representations of same collection: {}

Error message

Found two representations of same collection: {}

What it means

During flush, processReachableCollection looks up the CollectionEntry for a PersistentCollection in the persistence context. A null entry means this collection instance got into the flush graph without being properly registered - classically because the same collection instance is referenced by more than one entity (the comment points to StatefulPersistenceContext.addCollection(), which stores collections in an identity map keyed by the collection itself). Hibernate reports 'two representations' because the collection is being treated as the collection of two different owners/keys.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/internal/Collections.java:155

	 * @param collection The collection to be updated by reachability.
	 * @param type The type of the collection.
	 * @param entity The owner of the collection.
	 * @param session The session from which this request originates
	 */
	public static void processReachableCollection(
			PersistentCollection<?> collection,
			CollectionType type,
			Object entity,
			EventSource session,
			FlushProcessingContext flushProcessingContext) {
		collection.setOwner( entity );
		final var collectionEntry =
				session.getPersistenceContextInternal()
						.getCollectionEntry( collection );

		if ( collectionEntry == null ) {
			// refer to comment in StatefulPersistenceContext.addCollection()
			throw new HibernateException( "Found two representations of same collection: " + type.getRole() );
		}

		final var factory = session.getFactory();
		final var persister =
				factory.getMappingMetamodel()
						.getCollectionDescriptor( type.getRole() );

		collectionEntry.setCurrentPersister( persister );
		//TODO: better to pass the id in as an argument?
		collectionEntry.setCurrentKey( type.getKeyOfOwner( entity, session ) );

		final boolean isBytecodeEnhanced =
				persister.getOwnerEntityPersister()
						.getBytecodeEnhancementMetadata()
						.isEnhancedForLazyLoading();
		if ( isBytecodeEnhanced && !collection.wasInitialized() ) {
			// the class of the collection owner is enhanced for lazy loading,
			// and we found an un-initialized PersistentCollection, so skip it

View on GitHub (pinned to fad1729dce)

Solutions

  1. Never share collection instances between entities - copy the elements into a new collection: b.setOrders(new ArrayList<>(a.getOrders()));
  2. Fix shallow-copy utilities (BeanUtils.copyProperties, custom clone()) to deep-copy collection fields.
  3. Review test fixtures/object mothers that reuse the same List instance across multiple persisted entities.
  4. If two parents genuinely need the same children, model it as a proper many-to-many or re-parent the children explicitly instead of sharing the collection.

Example fix

// before - both entities reference the same PersistentCollection
b.setOrders(a.getOrders());
// after - each entity owns its own collection instance
b.setOrders(new ArrayList<>(a.getOrders()));
Defensive patterns

Strategy: validation

Validate before calling

// Guard: any assignment of a collection that may be Hibernate-managed must copy it
static <T> List<T> safeCopy(List<T> source) {
    return source == null ? null : new ArrayList<>(source);
}
// b.setOrders(safeCopy(a.getOrders()));  // never b.setOrders(a.getOrders());

Type guard

static boolean isHibernateManagedCollection(Object c) {
    return c instanceof org.hibernate.collection.spi.PersistentCollection;
}

Try / catch

catch (HibernateException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Found two representations of same collection")) {
        // role in message; find the shared instance and switch to a defensive copy
        throw new MappingMisuseException(e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Assigning one entity's collection instance to another entity: b.setOrders(a.getOrders()); copying state via BeanUtils/mapstruct with reference copy; reusing a detached collection instance across two managed entities; merge() of a graph where the same collection hangs off two parents. Thrown at flush with the collection role in the message.

Common situations: Object-mother/test builders sharing static collections between entities; clone/copy utilities doing shallow copies of collection fields; aggregate refactoring that moved a collection reference; legacy code that 'shares' a child list between two parent rows.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/a61605c2371eac00. Report an issue: GitHub.