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

  1. Add the SQL text as the <sql-query> element's content (CDATA is fine)
  2. Verify <return>/<return-join>/resultset-ref are accompanied by the SQL body, not used instead of it
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/b8983811475d237f. Report an issue: GitHub.