{"record":{"id":"90473772fbeee60b","repo":"hibernate/hibernate-orm","slug":"could-not-transform-the-raw-jdbc-value","errorCode":null,"errorMessage":"Could not transform the raw jdbc value","messagePattern":"Could not transform the raw jdbc value","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/type/OracleReflectionStructJdbcType.java","lineNumber":75,"sourceCode":"\t\t\t\t\t\t.getDatabase()\n\t\t\t\t\t\t.getDefaultNamespace()\n\t\t\t\t\t\t.locateUserDefinedType( Identifier.toIdentifier( sqlType ) )\n\t\t\t\t\t\t.getOrderMapping()\n\t\t);\n\t}\n\n\t@Override\n\tprotected Object transformRawJdbcValue(Object rawJdbcValue, WrapperOptions options) {\n\t\tMethod rawJdbcTransformer = RAW_JDBC_TRANSFORMER.get( rawJdbcValue.getClass() );\n\t\tif ( rawJdbcTransformer == null ) {\n\t\t\treturn rawJdbcValue;\n\t\t}\n\t\ttry {\n\t\t\treturn rawJdbcTransformer.invoke( rawJdbcValue,\n\t\t\t\t\toptions.getSession().getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() );\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new HibernateException( \"Could not transform the raw jdbc value\", e );\n\t\t}\n\t}\n\n}\n","sourceCodeStart":57,"sourceCodeEnd":80,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/type/OracleReflectionStructJdbcType.java#L57-L80","documentation":"When reading Oracle STRUCT column values through OracleReflectionStructJdbcType, Hibernate keeps per-class transformer Methods for oracle.sql types (TIMESTAMPTZ, TIMESTAMPLTZ, ...) that need the live connection to convert themselves to standard Java types. transformRawJdbcValue invokes that method reflectively; any invocation failure is wrapped in HibernateException. So the real cause is the driver object failing its own conversion - typically a closed/stale connection being passed to the conversion method, session-timezone problems, or an ojdbc version whose internal APIs differ.","triggerScenarios":"Selecting an entity mapped to an Oracle object type via OracleReflectionStructJdbcType whose attributes include TIMESTAMPTZ/TIMESTAMPLTZ/INTERVAL oracle.sql types, where the reflective conversion throws: the physical connection was closed before the struct was read (detached lazy access, pool eviction), the JDBC session timezone is invalid, or the ojdbc jar does not match the database.","commonSituations":"Lazy-loading struct-typed attributes after the session/connection closed; Oracle timestamps with time zone (TIMESTAMPTZ) read under a JVM/DB timezone mismatch ('oracle.jdbc.timezoneAsRegion' issues); mixing ojdbc versions with Oracle RAC/ASM upgrades.","solutions":["Read the caused-by exception first: ORA-17008 ClosedConnection means the struct was materialized after the connection closed - access struct attributes eagerly inside the transaction.","Set the session/JVM timezone explicitly (e.g. -Duser.timezone=... and -Doracle.jdbc.timezoneAsRegion=false) to fix timezone-based conversion failures.","Use an Oracle JDBC driver version matching the database release.","As a workaround, map the timestamp-with-timezone attribute as String inside the embeddable to bypass the oracle.sql conversion."],"exampleFix":"// before: struct attribute touched after session closed -> connection passed to\n// TIMESTAMPTZ.offsetDateTimeValue(connection) is already closed\nList<Order> orders = tx.inTx(s -> s.createQuery(...).getResultList());\norders.get(0).getDetails().getCreatedAt();   // lazy, session gone\n// after: force materialization inside the transaction\nList<Order> orders = tx.inTx(s -> {\n    List<Order> l = s.createQuery(...).getResultList();\n    l.forEach(o -> o.getDetails().getCreatedAt()); // read while connection live\n    return l;\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (HibernateException e) {\n    if (\"Could not transform the raw jdbc value\".equals(e.getMessage())) {\n        Throwable root = e.getCause();\n        // root is usually ClosedConnectionException (read after close) or a timezone error\n        log.error(\"Oracle struct read failed: {}\", root, e);\n        throw new DataAccessException(\"re-run the query with the session open\", e);\n    }\n    throw e;\n}","preventionTips":["Materialize struct attributes inside the owning transaction; never access them from detached entities.","Match the ojdbc driver version to the database release and keep it pinned.","Set -Duser.timezone and -Doracle.jdbc.timezoneAsRegion=false when TIMESTAMPTZ conversions misbehave."],"tags":["oracle","struct","reflection","timestamptz","jdbc-driver","connection-lifecycle"],"backgroundTag":"oracle-struct-value-conversion","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}