{"record":{"id":"1100b014c2962c4b","repo":"hibernate/hibernate-orm","slug":"write-expression-must-contain-exactly-one-value-pl","errorCode":null,"errorMessage":"write expression must contain exactly one value placeholder ('?') character near <column name=\"%s\" ... write=\"%s\" /> for <%s name=\"%s\" />","messagePattern":"write expression must contain exactly one value placeholder \\('\\?'\\) character near <column name=\"(.+?)\" \\.\\.\\. write=\"(.+?)\" /> for <(.+?) name=\"(.+?)\" />","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/RelationalValueSourceHelper.java","lineNumber":453,"sourceCode":"\t\t\t\terrorMessage = String.format(\n\t\t\t\t\t\tLocale.ENGLISH,\n\t\t\t\t\t\t\"write expression must contain exactly one value placeholder ('?') character near <column name=\\\"%s\\\" ... write=\\\"%s\\\" /> for <%s name=\\\"%s\\\" />\",\n\t\t\t\t\t\tcolumnMapping.getName(),\n\t\t\t\t\t\tcustomWrite,\n\t\t\t\t\t\tcolumnsAndFormulasSource.getSourceType().getElementName(),\n\t\t\t\t\t\tcolumnsAndFormulasSource.getSourceName()\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\terrorMessage = String.format(\n\t\t\t\t\t\tLocale.ENGLISH,\n\t\t\t\t\t\t\"write expression must contain exactly one value placeholder ('?') character near <column name=\\\"%s\\\" ... write=\\\"%s\\\" /> for <%s />\",\n\t\t\t\t\t\tcolumnMapping.getName(),\n\t\t\t\t\t\tcustomWrite,\n\t\t\t\t\t\tcolumnsAndFormulasSource.getSourceType().getElementName()\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new MappingException( errorMessage, sourceDocument.getOrigin() );\n\t\t}\n\t}\n\n}\n","sourceCodeStart":435,"sourceCodeEnd":458,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/RelationalValueSourceHelper.java#L435-L458","documentation":"A custom write fragment (write='...' on a <column>) is a SQL template used when Hibernate writes the column; exactly one '?' marks where the bound parameter is substituted. The binder validates the fragment with the pattern 'exactly one question mark' and rejects fragments containing zero or multiple placeholders, echoing the column name, the fragment, and the owning element.","triggerScenarios":"A <column> with write='now()' (zero placeholders), write='coalesce(?, ?)' or write=\"concat('P-', ?, '-', ?)\" (two or more placeholders). Zero-parameter and multi-parameter expressions both fail.","commonSituations":"Copy-pasting from read fragments (read= needs no placeholder); writing expressions that take several bound values; trying to escape a literal question mark by doubling it.","solutions":["Rewrite the fragment so it contains exactly one '?' where the value must be bound, e.g. write='upper(?)'","For zero-parameter expressions (constants, function results), prefer a database default or a generated column instead of a write fragment","If the expression genuinely needs two parameters, it cannot be a column write fragment - move the logic into a trigger or custom INSERT/UPDATE SQL"],"exampleFix":"// before\n<column name='code' write=\"concat('P-', ?, '-S')\" read=\"substr(code, 3)\"/>\n\n// after - exactly one placeholder\n<column name='code' write=\"concat('P-', upper(?))\" read=\"substr(code, 3)\"/>","handlingStrategy":"validation","validationCode":"// Pre-flight: custom write fragments must contain exactly one '?' placeholder\nString write = columnElement.getAttribute(\"write\");\nint placeholders = write.length() - write.replace(\"?\", \"\").length();\nif (placeholders != 1)\n    throw new IllegalArgumentException(\"write must contain exactly one '?', found \" + placeholders + \" in: \" + write);","typeGuard":null,"tryCatchPattern":"catch (org.hibernate.boot.MappingException e) at Metadata build: the message prints the column, fragment and owning element - rewrite the fragment so exactly one '?' marks the bound parameter","preventionTips":["Treat write fragments as single-parameter templates: exactly one '?'","For constant/function values use database defaults or generated columns instead","Unit-test a helper that counts placeholders in every write= attribute during build"],"tags":["hibernate","hbm","custom-sql","write-fragment","mapping","orm"],"backgroundTag":"sql-write-fragment-placeholder","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}