{"record":{"id":"63b4ff5c9cd07ece","repo":"hibernate/hibernate-orm","slug":"illegal-attempt-to-associate-a-collection-with-two","errorCode":null,"errorMessage":"Illegal attempt to associate a collection with two open sessions: ","messagePattern":"Illegal attempt to associate a collection with two open sessions: ","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java","lineNumber":773,"sourceCode":"\t\t\tallowLoadOutsideTransaction =\n\t\t\t\t\tfactory.getSessionFactoryOptions()\n\t\t\t\t\t\t\t.isInitializeLazyStateOutsideTransactionsEnabled();\n\n\t\t\tif ( allowLoadOutsideTransaction && sessionFactoryUuid == null ) {\n\t\t\t\tsessionFactoryUuid = factory.getUuid();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final boolean setCurrentSession(SharedSessionContractImplementor session) throws HibernateException {\n\t\tif ( session == this.session ) {\n\t\t\treturn false;\n\t\t}\n\t\telse if ( this.session != null ) {\n\t\t\tfinal String message = unexpectedSessionStateMessage( session );\n\t\t\tif ( isConnectedToSession() ) {\n\t\t\t\tthrow new HibernateException(\n\t\t\t\t\t\t\"Illegal attempt to associate a collection with two open sessions: \" + message\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tCOLLECTION_LOGGER.logUnexpectedSessionInCollectionNotConnected( message );\n\t\t\t}\n\t\t}\n\t\tif ( hasQueuedOperations() ) {\n\t\t\tCOLLECTION_LOGGER.queuedOperationWhenAttachToSession(\n\t\t\t\t\tcollectionInfoString( getRole(), getKey() ) );\n\t\t}\n\t\tthis.session = session;\n\t\treturn true;\n\t}\n\n\tprivate String unexpectedSessionStateMessage(SharedSessionContractImplementor session) {\n\t\t// NOTE: If this.session != null, this.session may be operating on this collection\n\t\t// (e.g., by changing this.role, this.key, or even this.session) in a different thread.","sourceCodeStart":755,"sourceCodeEnd":791,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java#L755-L791","documentation":"A PersistentCollection tracks the session it belongs to; setCurrentSession attaches it when an entity graph enters a session. If the collection is still connected to another open session, Hibernate throws this HibernateException: one collection instance cannot be managed by two open sessions at once. It signals managed entity instances (with their associations) shared across concurrent sessions.","triggerScenarios":"session2.update(sharedEntity) while session1 that loaded the entity is still open; caching managed entities in application code and reusing them across requests or threads; parallel processing touching lazy collections attached to different sessions.","commonSituations":"Application-level caches holding managed entities; entities passed between threads; two open EntityManagers in one request; long-lived session misuse.","solutions":["Do not share managed instances: re-load by id in each session, or cache ids/DTOs instead of entities","Use merge() from a clean detached state instead of attaching a shared instance to a second open session","Close or evict the entity from the first session before reattaching it elsewhere","Scope one session per unit of work per thread"],"exampleFix":"// before\nOrder shared = session1.find(Order.class, id); // session1 still open\nsession2.update(shared); // -> Illegal attempt to associate a collection with two open sessions\n\n// after\nOrder fresh = session2.find(Order.class, id); // or session2.merge(sharedDetached) after session1 closed","handlingStrategy":"validation","validationCode":"// only reattach a shared entity after its original session is gone\nif (sharedOrder != null && originalSession.isOpen()) {\n    originalSession.evict(sharedOrder); // detach first\n}\ntargetSession.update(sharedOrder);","typeGuard":null,"tryCatchPattern":"try {\n    session2.update(sharedEntity);\n} catch (HibernateException e) {\n    if (e.getMessage() != null\n            && e.getMessage().startsWith(\"Illegal attempt to associate a collection\")) {\n        session2.evict(sharedEntity);\n        sharedEntity = session2.merge(sharedEntity); // proper reattach path\n    } else {\n        throw e;\n    }\n}","preventionTips":["One session per unit of work; never share managed entities across threads","Cache DTOs or ids, not managed entity instances","Close the previous session before reattaching a detached graph","Prefer merge() over update() when reattaching possibly-shared instances"],"tags":["hibernate","session","collection","concurrency","detached"],"backgroundTag":"entity-shared-between-sessions","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}