Native Query Returning Multiple Rows Even When Repository Return Type Is String in Springboot 4.1.0

Description

Note: This behaviour is observed only in SpringBoot 4.1.0 which uses Hibernate Core 7.4.1.Final

in the later version of springnoot which 4.0.1 it is working fine springboot 4.0.1 uses Hibernate core 7.2.0.Final

A repository method is declared with a scalar return type (String) and executes a native query. If the native query returns more than one row, an exception is thrown indicating that multiple results were found.

Spring Boot Version

  • Spring Boot: 4.1.0

Expected Behavior

When the repository method return type is String, either:

  • The first matching row should be returned, or
  • The documentation should clearly state that native queries returning multiple rows are not supported for scalar return types.

Actual Behavior

If the native query returns more than one row, an exception similar to the following is thrown:

IncorrectResultSizeDataAccessException

(or the underlying JPA/Hibernate exception indicating multiple results were returned).

Example

@Query(value = """
    SELECT 'X'
    FROM SAMPLE_TABLE
    WHERE COLUMN_A = :valueA
      AND COLUMN_B = :valueB
      AND COLUMN_C = :valueC
      AND COLUMN_D = :valueD
    """, nativeQuery = true)
String checkRecord(
    @Param("valueA") String valueA,
    @Param("valueB") String valueB,
    @Param("valueC") String valueC,
    @Param("valueD") String valueD
);

If multiple rows match the query, the repository method throws an exception instead of returning a single `String`.

## Questions

- Is this the intended behavior for native queries with scalar return types?
- If so, should the framework require developers to explicitly limit the query (for example, using `FETCH FIRST 1 ROW ONLY` or `LIMIT 1`)?

Because of this our applications are breaking at runtime.. Please guide us through 7.4.1 migration

reproducer GitHub - FuncGuy/spring-boot-native-query-regression · GitHub

This is expected behavior, as per specification of the Query#getSingleResult() method which is used behind the scenes. The fact that the result was uniqued before was wrong.