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

  1. Pick one style: either keep resultSetMapping and delete the columns attribute, or keep the inline columns and delete resultSetMapping.
  2. If the mapping is shared by several native queries, extract it to @SqlResultSetMapping(name=...) and reference it with resultSetMapping only.
  3. 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

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


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