hibernate/hibernate-orm · error · MappingException
Named native query [%s] did not specify query string
Error message
Named native query [%s] did not specify query string
What it means
The native-SQL counterpart of the HQL check: a <sql-query name='...'> must include the SQL text as one of its content items. The walker sets foundQuery only when processNamedQueryContentItem actually consumed the query string; if the element holds only <return>/<return-join>/resultset-ref/ synchronization elements and no SQL text, this MappingException is thrown. The same binder then also rejects combining resultset-ref with inline returns, underlining that returns complement - never replace - the SQL body.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/NamedQueryBinder.java:135
final var implicitResultSetMappingBuilder =
new ImplicitHbmResultSetMappingDescriptorBuilder( registrationName, context );
boolean foundQuery = false;
for ( Object content : namedQueryBinding.getContent() ) {
final boolean wasQuery = processNamedQueryContentItem(
content,
builder,
implicitResultSetMappingBuilder,
namedQueryBinding,
context
);
if ( wasQuery ) {
foundQuery = true;
}
}
if ( !foundQuery ) {
throw new MappingException(
"Named native query [%s] did not specify query string"
.formatted( namedQueryBinding.getName() ),
context.getOrigin()
);
}
final var collector = context.getMetadataCollector();
if ( implicitResultSetMappingBuilder.hasAnyReturns() ) {
if ( isNotEmpty( namedQueryBinding.getResultsetRef() ) ) {
throw new MappingException(
"Named native query [%s] specified both a resultset-ref and an inline mapping of results"
.formatted( namedQueryBinding.getName() ),
context.getOrigin()
);
}
collector.addResultSetMapping( implicitResultSetMappingBuilder.build( context ) );View on GitHub (pinned to fad1729dce)
Solutions
- Add the SQL text as the <sql-query> element's content (CDATA is fine)
- Verify <return>/<return-join>/resultset-ref are accompanied by the SQL body, not used instead of it
- Add a build-time check that every <sql-query> element has non-blank text content
Example fix
// before
<sql-query name='findUsers'>
<return alias='u' class='User'/>
</sql-query>
// after
<sql-query name='findUsers'>
<return alias='u' class='User'/>
<![CDATA[SELECT {u.*} FROM users u WHERE u.status = 'A']]>
</sql-query> Defensive patterns
Strategy: validation
Validate before calling
NodeList sqlQueries = doc.getElementsByTagName("sql-query");
for (int i = 0; i < sqlQueries.getLength(); i++) {
Element q = (Element) sqlQueries.item(i);
boolean hasSql = q.getTextContent() != null && !q.getTextContent().isBlank();
if (!hasSql) {
throw new IllegalStateException("named native query '" + q.getAttribute("name") + "' has no SQL text");
}
} Try / catch
catch (MappingException e) at bootstrap; the message names the empty native query. Add the SQL body (CDATA is fine) alongside any <return> declarations and rebuild.
Prevention
- Treat <return>/<return-join> as complements to the SQL body, never replacements
- Add a CI lint that every <sql-query> has non-blank text content
- Prefer CDATA-wrapped SQL to survive XML edits and tooling
When it happens
Trigger: <sql-query name='x'><return alias='u' class='User'/></sql-query> with no actual SQL text; SQL moved out to an external file leaving an empty element; CDATA-wrapped SQL dropped during migration.
Common situations: Refactoring native queries into code or repositories and leaving stubs in the mapping; copy-pasting result-mapping-only templates; editing tools that strip CDATA bodies.
Related errors
- Named query [%s] did not specify query string
- Class or package level '@NamedNativeQuery' annotation must s
- Named native query '%s' specified both 'resultSetMapping' an
- filter alias must define either table or entity attribute
- must specify an identifier type: %s
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b8983811475d237f.
Report an issue: GitHub.