{"record":{"id":"d2ffee767b33a3e4","repo":"hibernate/hibernate-orm","slug":"unable-to-set-nclob-string-after-creation","errorCode":null,"errorMessage":"Unable to set NCLOB string after creation","messagePattern":"Unable to set NCLOB string after creation","errorType":"exception","errorClass":"JDBCException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/StandardLobCreator.java","lineNumber":51,"sourceCode":"\n\t/**\n\t * Create the basic contextual NCLOB reference.\n\t *\n\t * @return The created NCLOB reference.\n\t */\n\tpublic NClob createNClob() {\n\t\treturn lobCreationContext.fromContext( CREATE_NCLOB_CALLBACK );\n\t}\n\n\t@Override\n\tpublic NClob createNClob(String string) {\n\t\ttry {\n\t\t\tfinal NClob nclob = createNClob();\n\t\t\tnclob.setString( 1, string );\n\t\t\treturn nclob;\n\t\t}\n\t\tcatch ( SQLException e ) {\n\t\t\tthrow new JDBCException( \"Unable to set NCLOB string after creation\", e );\n\t\t}\n\t}\n\n\t@Override\n\tpublic NClob createNClob(Reader reader, long length) {\n\t\t// IMPL NOTE : it is inefficient to use JDBC LOB locator creation to create a LOB\n\t\t// backed by a given stream.  So just wrap the stream (which is what the NonContextualLobCreator does).\n\t\treturn NonContextualLobCreator.INSTANCE.createNClob( reader, length );\n\t}\n}\n","sourceCodeStart":33,"sourceCodeEnd":62,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/StandardLobCreator.java#L33-L62","documentation":"StandardLobCreator.createNClob(String) obtains an empty NClob through Connection.createNClob() (via LobCreationContext) and then fills it with nclob.setString(1, string). Any SQLException from that flow is wrapped as JDBCException 'Unable to set NCLOB string after creation'.","triggerScenarios":"Calling Hibernate.getLobHelper().createNClob(String), or persisting a nationalized String that the dialect maps to connection-created NClob, on a driver/DB where createNClob() or NClob.setString() fails: connection already closed, NCLOB support absent, or driver bugs.","commonSituations":"Drivers with partial national-character support; pooled connections that get validated/closed between LOB creation and setString; databases whose national charset is not configured.","solutions":["Prefer mapping the field as @Nationalized String and let Hibernate choose NonContextualLobCreator (stream wrapping) instead of creating NClobs by hand","Test Connection.createNClob() + setString() directly on your driver to confirm support and capture the real SQLException","Upgrade the JDBC driver / database if the NClob write path is buggy","Ensure the Session/connection stays open until flush completes"],"exampleFix":"// before: manual NClob creation\nentity.setNote(session.getLobHelper().createNClob(bigText));\n\n// after: let Hibernate manage nationalized text\n@Nationalized String note; // on the entity","handlingStrategy":"try-catch","validationCode":"// prove driver NClob support once at startup\ntry (Connection c = dataSource.getConnection()) {\n    NClob n = c.createNClob();\n    n.setString(1, \"ping\");\n    n.free();\n}","typeGuard":null,"tryCatchPattern":"try {\n    entity.setNote(lobHelper.createNClob(text));\n}\ncatch (JDBCException e) {\n    // fall back to plain String / @Nationalized mapping\n    entity.setNote(text);\n}","preventionTips":["Prefer @Nationalized String attributes over manual NClob creation","Validate driver NCLOB support in CI against the real DB","Keep the owning session open until flush"],"tags":["nclob","lob","nationalized","jdbc","hibernate"],"backgroundTag":"lob-creation-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}