hibernate/hibernate-orm · error · AnnotationException
Named native query '%s' specified both 'resultSetMapping' an
Error message
Named native query '%s' specified both 'resultSetMapping' and an inline result set mapping
What it means
A jakarta.persistence @NamedNativeQuery can define its result mapping two ways: referencing an existing @SqlResultSetMapping via resultSetMapping=, or inline via the columns attribute (@EntityResult/@ConstructorResult/@ColumnResult). hasInlineResultSetMapping detects the inline form; if resultSetMapping is also non-blank, AnnotationException is thrown because the two sources conflict.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java:184
if ( namedNativeQuery != null ) {
final String registrationName = namedNativeQuery.name();
final String queryString = namedNativeQuery.query();
if ( registrationName.isBlank() ) {
throw new AnnotationException(
"Class or package level '@NamedNativeQuery' annotation must specify a 'name'" );
}
if ( BOOT_LOGGER.isTraceEnabled() ) {
BOOT_LOGGER.bindingNamedNativeQuery( registrationName,
queryString.replace( '\n', ' ' ) );
}
final var collector = context.getMetadataCollector();
final String resultSetMappingName;
if ( hasInlineResultSetMapping( namedNativeQuery ) ) {
resultSetMappingName = registrationName;
if ( !namedNativeQuery.resultSetMapping().isBlank() ) {
throw new AnnotationException(
"Named native query '%s' specified both 'resultSetMapping' and an inline result set mapping"
.formatted( registrationName )
);
}
final var mappingDefinition =
SqlResultSetMappingDescriptor.from(
namedNativeQuery,
location == null ? null : location.getName()
);
if ( isDefault ) {
collector.addDefaultResultSetMapping( mappingDefinition );
}
else {
collector.addResultSetMapping( mappingDefinition );
}
}
else {View on GitHub (pinned to fad1729dce)
Solutions
- Pick one style: either keep resultSetMapping and delete the columns attribute, or keep the inline columns and delete resultSetMapping.
- If the mapping is shared by several native queries, extract it to @SqlResultSetMapping(name=...) and reference it with resultSetMapping only.
- Add a quick review check that no @NamedNativeQuery sets both attributes.
Example fix
// before
@NamedNativeQuery(
name = "Person.findNative",
query = "SELECT id, name FROM person",
resultSetMapping = "personMapping",
columns = @EntityResult(entityClass = Person.class)) // conflict
// after (option A: reference only)
@NamedNativeQuery(
name = "Person.findNative",
query = "SELECT id, name FROM person",
resultSetMapping = "personMapping")
// after (option B: inline only)
@NamedNativeQuery(
name = "Person.findNative",
query = "SELECT id, name FROM person",
columns = @EntityResult(entityClass = Person.class)) Defensive patterns
Strategy: validation
Validate before calling
@Test void nativeQueriesDeclareOneMappingStyle() {
for (NamedNativeQuery q : Order.class.getAnnotationsByType(NamedNativeQuery.class)) {
boolean inline = q.columns().length > 0;
boolean referenced = !q.resultSetMapping().isBlank();
assertTrue(!(inline && referenced),
q.name() + " sets both resultSetMapping and inline columns");
}
} Try / catch
try {
metadata = sources.buildMetadata();
} catch (AnnotationException e) {
failBuild("Result mapping conflict: " + e.getMessage());
} Prevention
- Choose one mapping style per native query and enforce it in review.
- Extract shared mappings to @SqlResultSetMapping and reference them by name.
When it happens
Trigger: @NamedNativeQuery(name = "x", query = "...", resultSetMapping = "xMapping", columns = { @EntityResult(entityClass = Person.class) }) — both mechanisms present. Fires only when the inline mapping is detected AND the reference is non-blank.
Common situations: Starting with an inline mapping and later adding resultSetMapping without removing columns; merging query definitions in pull requests; copy-paste between queries that use the other style.
Related errors
- Result-set mapping was null
- Result-set mapping name is null: {}
- Duplicate SQL result set mapping '{}'
- Identifier property '" + getPath( holder, data ) + "' cannot
- Attribute '%s' of entity '%s' is mapped by association '%s'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/84f41b1bb91c6bdc.
Report an issue: GitHub.