hibernate/hibernate-orm · error · MappingException
Named native query [%s] specified both a resultset-ref and a
Error message
Named native query [%s] specified both a resultset-ref and an inline mapping of results
What it means
Hibernate binds each hbm.xml <sql-query> by folding its inline return elements (<return/>, <return-scalar/>, <return-join/>, <load-collection/>) into an implicit result-set mapping. A named native query may describe its results either through that inline mapping or by referencing a separately declared <resultset> via the resultset-ref attribute - never both. When at least one inline return exists and resultset-ref is also non-empty, NamedQueryBinder aborts bootstrap with this MappingException.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/NamedQueryBinder.java:146
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 ) );
builder.setResultSetMappingName( implicitResultSetMappingBuilder.getRegistrationName() );
}
if ( namedQueryBinding.isCallable() ) {
final var definition =
createStoredProcedure( builder, context,
() -> illegalCallSyntax( context, namedQueryBinding, builder.getSqlString() ) );
collector.addNamedProcedureCallDefinition( definition );
DEPRECATION_LOGGER.callableNamedNativeQuery();
}
else {View on GitHub (pinned to fad1729dce)
Solutions
- Choose one style: delete the resultset-ref attribute and keep the inline <return*> elements, or delete the inline elements and keep resultset-ref pointing at an existing <resultset name='personRs'> definition
- Verify the referenced <resultset> actually exists in the same document or an included one
- Validate the corrected file against the Hibernate hbm XSD to catch similar conflicting declarations
Example fix
// before - hbm.xml
<sql-query name='findAll' resultset-ref='personRs'>
<return-scalar column='id'/>
<return-scalar column='name'/>
</sql-query>
// after - inline mapping kept, resultset-ref removed
<sql-query name='findAll'>
<return-scalar column='id'/>
<return-scalar column='name'/>
</sql-query> Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight scan of every hbm.xml before building the SessionFactory
var doc = javax.xml.parsers.DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(hbmFile);
var queries = doc.getElementsByTagName("sql-query");
for (int i = 0; i < queries.getLength(); i++) {
var q = (org.w3c.dom.Element) queries.item(i);
boolean hasRef = !q.getAttribute("resultset-ref").isEmpty();
boolean hasInline = q.getElementsByTagName("return").getLength() > 0
|| q.getElementsByTagName("return-scalar").getLength() > 0
|| q.getElementsByTagName("return-join").getLength() > 0
|| q.getElementsByTagName("load-collection").getLength() > 0;
if (hasRef && hasInline)
throw new IllegalStateException("sql-query '" + q.getAttribute("name")
+ "' mixes resultset-ref with inline returns");
} Try / catch
try { Metadata metadata = metadataBuilder.build(); } catch (org.hibernate.boot.MappingException e) { /* message names the offending query; getOrigin() points at the hbm.xml source - surface both as a configuration error and stop startup */ throw new IllegalStateException("Bad native-query mapping: " + e.getMessage(), e); } Prevention
- Run xmllint --schema with the Hibernate hbm XSD over all mapping files in CI
- Standardize on one native-query result-mapping style (inline vs resultset-ref) per codebase and lint for the other
- When refactoring to resultset-ref, grep the file for <return before deleting the <resultset> definition, and vice versa
When it happens
Trigger: An hbm.xml contains <sql-query name='findAll' resultset-ref='personRs'> that also declares at least one inline return child such as <return-scalar column='id'/> or <return alias='p' class='com.Person'/>. Thrown during Metadata building (SessionFactory bootstrap), before any query executes.
Common situations: Migrating between inline returns and shared named <resultset> definitions and leaving both halves in the file; merging two query definitions during copy-paste; hand-maintained legacy hbm.xml that never went through XSD validation.
Related errors
- Encountered unexpected content type [%s] for named native qu
- Named native query definition object is null
- Named native query definition name is null: {}
- <many-to-any /> mapping [%s] needs to specify 2 or more colu
- <many-to-any /> mapping [%s] needs to specify 2 or more colu
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1cc8fd29d64db156.
Report an issue: GitHub.