{"record":{"id":"f816113d6e983033","repo":"hibernate/hibernate-orm","slug":"hibernate-cannot-unwrap-entitymanagerfactory-as","errorCode":null,"errorMessage":"Hibernate cannot unwrap EntityManagerFactory as '{type.getName()}'","messagePattern":"Hibernate cannot unwrap EntityManagerFactory as '(.+?)'","errorType":"exception","errorClass":"PersistenceException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java","lineNumber":1265,"sourceCode":"\t\t}\n\n\t\tif ( type.isInstance( runtimeMetamodels ) ) {\n\t\t\treturn type.cast( runtimeMetamodels );\n\t\t}\n\n\t\tif ( type.isInstance( runtimeMetamodels.getJpaMetamodel() ) ) {\n\t\t\treturn type.cast( runtimeMetamodels.getJpaMetamodel() );\n\t\t}\n\n\t\tif ( type.isInstance( runtimeMetamodels.getMappingMetamodel() ) ) {\n\t\t\treturn type.cast( runtimeMetamodels.getMappingMetamodel() );\n\t\t}\n\n\t\tif ( type.isInstance( queryEngine ) ) {\n\t\t\treturn type.cast( queryEngine );\n\t\t}\n\n\t\tthrow new PersistenceException( \"Hibernate cannot unwrap EntityManagerFactory as '\" + type.getName() + \"'\" );\n\t}\n\n\t@Override\n\tpublic void runInTransaction(@Nonnull Consumer<EntityManager> work) {\n\t\tinTransaction( work );\n\t}\n\n\t@Override\n\tpublic <H extends EntityHandler> void runInTransaction(\n\t\t\t@Nonnull Class<H> handlerType, @Nonnull Consumer<H> consumer) {\n\t\tif ( EntityManager.class.isAssignableFrom( handlerType ) ) {\n\t\t\t//noinspection unchecked\n\t\t\tinTransaction( (Consumer<EntityManager>) consumer );\n\t\t}\n\t\telse if ( EntityAgent.class.isAssignableFrom( handlerType ) ) {\n\t\t\t//noinspection unchecked\n\t\t\tinStatelessTransaction( (Consumer<EntityAgent>) consumer );\n\t\t}","sourceCodeStart":1247,"sourceCodeEnd":1283,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java#L1247-L1283","documentation":"JPA's EntityManagerFactory.unwrap(Class) must succeed for implementor classes and the JPA interfaces, and throw PersistenceException otherwise. Hibernate supports unwrapping to SessionFactory/SessionFactoryImplementor, EntityManagerFactory, the JpaMetamodel/MappingMetamodel, and the QueryEngine; anything else (e.g. javax.persistence.EntityManagerFactory variants of another provider, DataSource, custom classes) reaches the terminal PersistenceException.","triggerScenarios":"Calling emf.unwrap(SomeClass.class) with a type outside Hibernate's supported set — e.g. unwrap(DataSource.class), unwrap(Session.class) (sessions come from EntityManager.unwrap, not the factory), or a class from a different JPA provider. Each branch in unwrap() does type.isInstance(...) and the final else throws.","commonSituations":"Copy-pasted unwrap(Session.class) or unwrap(Connection.class) code intended for EntityManager; portability layers that unwrap to provider-specific classes; using the older javax vs jakarta EntityManagerFactory class object after a Jakarta migration.","solutions":["Unwrap the EntityManager (not the factory) to get Session/SessionImplementor: em.unwrap(Session.class)","Use only documented targets on the factory: SessionFactory.class, SessionFactoryImplementor.class, Metamodel/JpaMetamodel, MappingMetamodel, QueryEngine, EntityManagerFactory.class","To reach the DataSource, unwrap the ServiceRegistry instead: sf.getServiceRegistry().requireService(ConnectionProvider.class)","After jakarta migration, make sure you pass the jakarta.persistence classes, not javax.persistence leftovers"],"exampleFix":"// before\nSession session = emf.unwrap(Session.class); // PersistenceException: cannot unwrap\n\n// after\nSession session = entityManager.unwrap(Session.class);\n// or, for factory-level needs:\nSessionFactoryImplementor sfi = emf.unwrap(SessionFactoryImplementor.class);","handlingStrategy":"type-guard","validationCode":"static final Set<Class<?>> FACTORY_UNWRAP_TARGETS = Set.of(\n        EntityManagerFactory.class, SessionFactory.class,\n        SessionFactoryImplementor.class, Metamodel.class);\n\nif (FACTORY_UNWRAP_TARGETS.contains(type)) {\n    return emf.unwrap(type);\n}","typeGuard":"static boolean factoryUnwrappable(Class<?> t) {\n    return EntityManagerFactory.class.equals(t)\n            || SessionFactory.class.equals(t)\n            || SessionFactoryImplementor.class.equals(t)\n            || Metamodel.class.isAssignableFrom(t)\n            || t.getName().startsWith(\"org.hibernate.engine.query.spi.QueryEngine\");\n}","tryCatchPattern":"try {\n    SessionFactory sf = emf.unwrap(SessionFactory.class);\n} catch (PersistenceException e) {\n    // type not supported by Hibernate's factory unwrap — use a dedicated accessor instead\n    throw new UnsupportedOperationException(\"Cannot unwrap EMF to \" + type, e);\n}","preventionTips":["Remember the split: EntityManager.unwrap for Session, EntityManagerFactory.unwrap for factory/metamodel","Unwrap to the stable public interfaces (SessionFactory, Metamodel) rather than internals unless required","After jakarta migration, purge stale javax.persistence imports so unwrap targets match"],"tags":["hibernate","jpa","unwrap","api-misuse","type-mismatch"],"backgroundTag":"jpa-unwrap-failure","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}