hibernate/hibernate-orm · error · HibernateException
The database returned no natively generated values : {}
Error message
The database returned no natively generated values : {} What it means
After inserting/updating a row whose values are generated by the database (identity ids, @GeneratedColumn columns, defaults read back via RETURNING/getGeneratedKeys), Hibernate consumes the statement's generated-values result. If that result contains no row at all, this HibernateException is thrown — the dialect/driver expected retrievable generated values but the execution returned none.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/generator/values/internal/GeneratedValuesHelper.java:174
mappingProducer.resolve( directResultSetAccess, influencers, factory ),
null,
executionContext
);
final var valuesProcessingState =
new JdbcValuesSourceProcessingStateStandardImpl( executionContext, NO_OPTIONS );
final RowReader<Object[]> rowReader = ResultsHelper.createRowReader(
factory,
RowTransformerArrayImpl.instance(),
Object[].class,
jdbcValues
);
final var rowProcessingState =
new RowProcessingStateStandardImpl( valuesProcessingState, executionContext, rowReader, jdbcValues );
final List<Object[]> results =
ListResultsConsumer.<Object[]>instance( ListResultsConsumer.UniqueSemantic.NONE )
.consume( jdbcValues, session, NO_OPTIONS, valuesProcessingState, rowProcessingState, rowReader );
if ( results.isEmpty() ) {
throw new HibernateException( "The database returned no natively generated values : "
+ persister.getNavigableRole().getFullPath() );
}
return results.get( 0 );
}
/**
* Utility method that instantiates a {@link JdbcValuesMappingProducer} so it can be cached by the
* {@link GeneratedValuesMutationDelegate delegates} when they are instantiated.
*
* @param persister the current entity persister
* @param timing the timing of the mutation operation
* @param supportsArbitraryValues if we should process arbitrary (non-identifier) generated values
* @param supportsRowId if we should process {@link org.hibernate.metamodel.mapping.EntityRowIdMapping rowid}s
* {@code false} if we should retrieve the index through the column expression
*
* @return the instantiated jdbc values mapping producer
*/
public static GeneratedValuesMappingProducer createMappingProducer(View on GitHub (pinned to fad1729dce)
Solutions
- Switch the identifier from IDENTITY to SEQUENCE (+ allocationSize) so ids are fetched before insert and no getGeneratedKeys/RETURNING roundtrip is needed
- If the table has a trigger, fix it so the generated columns are still returned (SQL Server: avoid result-set-eating trigger patterns)
- Upgrade the JDBC driver to a version known to return generated keys correctly (mssql-jdbc over jTDS, current Jaybird, current ojdbc)
- For view/INSTEAD OF trigger mappings, remove database-side generation annotations and read values explicitly after flush
- Verify the configured dialect matches your database version
Example fix
// before — identity + trigger on SQL Server returns no generated-keys row @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; // after — sequence: id fetched before insert, no readback dependency @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "order_seq") @SequenceGenerator(name = "order_seq", sequenceName = "order_seq", allocationSize = 50) Long id;
Defensive patterns
Strategy: try-catch
Try / catch
try {
session.persist(order);
session.flush();
}
catch (HibernateException e) {
if (e.getMessage() != null
&& e.getMessage().startsWith("The database returned no natively generated values")) {
// the row may exist without a returned id: do NOT blind-retry the insert;
// re-query by natural/unique key, or roll back and switch to sequence-based ids
throw new GeneratedKeysUnavailableException(order, e);
}
throw e;
} Prevention
- Prefer SEQUENCE over IDENTITY where the dialect supports it
- Audit any trigger added to tables used with identity or generated columns
- Pin recent JDBC drivers and run insert-readback tests in CI against the real database
- Avoid @GeneratedColumn on views with INSTEAD OF triggers
When it happens
Trigger: INSERT on a table where the generated-values result comes back empty: SQL Server tables with triggers (the classic getGeneratedKeys case returning zero rows), PostgreSQL INSTEAD OF triggers on views suppressing the RETURNING row, older JDBC drivers (jTDS, old Jaybird/Firebird, old Oracle) that fail to return generated keys, or a dialect relying on RETURNING against a database that does not deliver it.
Common situations: Adding an audit trigger to a legacy table that already used GenerationType.IDENTITY; mapping entities onto views with INSTEAD OF triggers plus @GeneratedColumn; driver upgrades/downgrades; migration between identity and sequence strategies.
Related errors
- getGeneratedKeys() support is not enabled
- getGeneratedKeys() support is not enabled
- ${getClass().getName()} does not support selecting the last
- JDBC driver does not support named parameters for setArray.
- Null id generated for entity '%s'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b8b52563af5c1033.
Report an issue: GitHub.