{"record":{"id":"a61605c2371eac00","repo":"hibernate/hibernate-orm","slug":"found-two-representations-of-same-collection","errorCode":null,"errorMessage":"Found two representations of same collection: {}","messagePattern":"Found two representations of same collection: (.+?)","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/internal/Collections.java","lineNumber":155,"sourceCode":"\t * @param collection The collection to be updated by reachability.\n\t * @param type The type of the collection.\n\t * @param entity The owner of the collection.\n\t * @param session The session from which this request originates\n\t */\n\tpublic static void processReachableCollection(\n\t\t\tPersistentCollection<?> collection,\n\t\t\tCollectionType type,\n\t\t\tObject entity,\n\t\t\tEventSource session,\n\t\t\tFlushProcessingContext flushProcessingContext) {\n\t\tcollection.setOwner( entity );\n\t\tfinal var collectionEntry =\n\t\t\t\tsession.getPersistenceContextInternal()\n\t\t\t\t\t\t.getCollectionEntry( collection );\n\n\t\tif ( collectionEntry == null ) {\n\t\t\t// refer to comment in StatefulPersistenceContext.addCollection()\n\t\t\tthrow new HibernateException( \"Found two representations of same collection: \" + type.getRole() );\n\t\t}\n\n\t\tfinal var factory = session.getFactory();\n\t\tfinal var persister =\n\t\t\t\tfactory.getMappingMetamodel()\n\t\t\t\t\t\t.getCollectionDescriptor( type.getRole() );\n\n\t\tcollectionEntry.setCurrentPersister( persister );\n\t\t//TODO: better to pass the id in as an argument?\n\t\tcollectionEntry.setCurrentKey( type.getKeyOfOwner( entity, session ) );\n\n\t\tfinal boolean isBytecodeEnhanced =\n\t\t\t\tpersister.getOwnerEntityPersister()\n\t\t\t\t\t\t.getBytecodeEnhancementMetadata()\n\t\t\t\t\t\t.isEnhancedForLazyLoading();\n\t\tif ( isBytecodeEnhanced && !collection.wasInitialized() ) {\n\t\t\t// the class of the collection owner is enhanced for lazy loading,\n\t\t\t// and we found an un-initialized PersistentCollection, so skip it","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/internal/Collections.java#L137-L173","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Never share collection instances between entities - copy the elements into a new collection: b.setOrders(new ArrayList<>(a.getOrders()));","Fix shallow-copy utilities (BeanUtils.copyProperties, custom clone()) to deep-copy collection fields.","Review test fixtures/object mothers that reuse the same List instance across multiple persisted entities.","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."],"exampleFix":"// before - both entities reference the same PersistentCollection\nb.setOrders(a.getOrders());\n// after - each entity owns its own collection instance\nb.setOrders(new ArrayList<>(a.getOrders()));","handlingStrategy":"validation","validationCode":"// Guard: any assignment of a collection that may be Hibernate-managed must copy it\nstatic <T> List<T> safeCopy(List<T> source) {\n    return source == null ? null : new ArrayList<>(source);\n}\n// b.setOrders(safeCopy(a.getOrders()));  // never b.setOrders(a.getOrders());","typeGuard":"static boolean isHibernateManagedCollection(Object c) {\n    return c instanceof org.hibernate.collection.spi.PersistentCollection;\n}","tryCatchPattern":"catch (HibernateException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Found two representations of same collection\")) {\n        // role in message; find the shared instance and switch to a defensive copy\n        throw new MappingMisuseException(e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Treat entity getters that return collections as read-only views; always copy elements out.","Review clone/copy utilities so collection fields are deep-copied.","In test object mothers, create fresh collections per entity, never shared static ones."],"tags":["collection","shared-reference","flush","entity-graph","mapping"],"backgroundTag":"shared-collection-instance","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}