Hide
The manual needs a section on sequence-style identifier generation, which this ticket makes available for the first time.
- @GeneratedValue is supported with strategy AUTO or SEQUENCE, for identifiers of type Short, Integer or Long. It was previously rejected at boot, so this is new surface rather than a change.
- The counter collection is named hibernate_sequences, and that name is fixed rather than configurable. Every sequence in the application is one document in it, keyed by the Hibernate sequence name, which defaults to <table>_SEQ. Users need to know the collection appears in their database, that schema export creates and seeds it, that dropping the schema deletes its documents, and that mapping an entity onto that collection name is rejected at boot.
Hand-creating the counter document
A deployment that runs with schema management turned off, which is common in production, has to create the counter document itself. One document per sequence in hibernate_sequences:
db.hibernate_sequences.insertOne({
_id: "books_SEQ", next_value: NumberLong(1), increment: NumberLong(50) })
Getting it wrong is now reported rather than silent, and the manual can say so. Each of these was measured:
- increment not equal to the generator's allocationSize fails while building the SessionFactory, with Hibernate ORM's own message: "The increment size of the [books_SEQ] sequence is set to [50] in the entity mapping but the mapped database sequence increment size is [1]".
- increment omitted fails the same way, reporting the database increment as 0.
- next_value or increment stored as a 32-bit integer, which is what typing next_value: 1 in mongosh produces, fails while building the SessionFactory with "Value expected to be of type INT64 is of unexpected type INT32". NumberLong is required.
- next_value omitted fails at the first allocation with "[findAndModify] matched no document", followed by the command, which shows the required shape.
- A missing document fails at the first allocation with an error naming the sequence.
A gap the manual should still warn about
- A sequence in a non-default schema is not covered by the increment check, on any dialect. Hibernate ORM's check requires the extracted schema to be null or the current schema, so a sequence declared with a schema qualifier is skipped whether the database is MongoDB or PostgreSQL. This is SQL parity, not a MongoDB shortcoming, but the consequence is worth stating: measured here, a generator with schema = "billing", sequenceName = "qr_numbers" and allocationSize = 50, against a counter document saying increment: 1, booted with no error and produced the identifiers 1, -47, -46. Users who both declare a schema on the generator and create the counter document by hand must get increment right themselves.
Other behaviour to document
- Identifier allocation does not take part in the caller's transaction, which matches native SQL sequences. An allocated value is not returned when a transaction rolls back, so gaps between persisted identifiers are expected. A pooled optimizer also leaves a gap when a SessionFactory closes with part of its block unused, which with the default allocation size of 50 can be up to 49 identifiers per process.
- Supported optimizers are none, pooled, pooled-lo, hilo and legacy-hilo. The last two are selected with the hibernate.id.optimizer.pooled.preferred setting.
- Rejected at boot, each with a message giving the reason: GenerationType.IDENTITY (MongoDB has no auto-increment field and no way to return a generated key from an insert; use SEQUENCE, or the extension's @ObjectIdGenerator for a database-chosen identifier), GenerationType.TABLE (HIBERNATE-252), GenerationType.UUID (HIBERNATE-121), BigInteger and BigDecimal identifiers (HIBERNATE-253), a non-blank @SequenceGenerator(options), and a @GeneratedValue(generator) name that resolves to a non-sequence generator such as identity or increment, and a sequence qualified by a catalog.
The catalog one needs explaining in the manual, because the spelling is not guessable. Hibernate ORM reads a three-part sequenceName such as a.b.c as catalog a, schema b, sequence c, and this extension supports no catalog. Before it was rejected, the catalog was dropped when the counter key was formed, so that sequence shared one counter document with a plain schema = "b", sequenceName = "c" and two entities drew identifiers from the same counter.
- HQL insert ... select into an entity with a generated identifier remains unsupported, because MQL cannot embed an allocation inside another statement.
Show
The manual needs a section on sequence-style identifier generation, which this ticket makes available for the first time.
@GeneratedValue is supported with strategy AUTO or SEQUENCE , for identifiers of type Short , Integer or Long . It was previously rejected at boot, so this is new surface rather than a change.
The counter collection is named hibernate_sequences , and that name is fixed rather than configurable. Every sequence in the application is one document in it, keyed by the Hibernate sequence name, which defaults to <table>_SEQ . Users need to know the collection appears in their database, that schema export creates and seeds it, that dropping the schema deletes its documents, and that mapping an entity onto that collection name is rejected at boot.
Hand-creating the counter document
A deployment that runs with schema management turned off, which is common in production, has to create the counter document itself. One document per sequence in hibernate_sequences :
db.hibernate_sequences.insertOne({
_id: "books_SEQ" , // the sequence name, by default <table>_SEQ
next_value: NumberLong(1), // the value the next allocation hands out
increment: NumberLong(50) // must equal the generator's allocationSize
})
Getting it wrong is now reported rather than silent, and the manual can say so. Each of these was measured:
increment not equal to the generator's allocationSize fails while building the SessionFactory, with Hibernate ORM's own message: "The increment size of the [books_SEQ] sequence is set to [50] in the entity mapping but the mapped database sequence increment size is [1] ".
increment omitted fails the same way, reporting the database increment as 0.
next_value or increment stored as a 32-bit integer, which is what typing next_value: 1 in mongosh produces, fails while building the SessionFactory with "Value expected to be of type INT64 is of unexpected type INT32". NumberLong is required.
next_value omitted fails at the first allocation with " [findAndModify] matched no document", followed by the command, which shows the required shape.
A missing document fails at the first allocation with an error naming the sequence.
A gap the manual should still warn about
A sequence in a non-default schema is not covered by the increment check, on any dialect. Hibernate ORM's check requires the extracted schema to be null or the current schema, so a sequence declared with a schema qualifier is skipped whether the database is MongoDB or PostgreSQL. This is SQL parity, not a MongoDB shortcoming, but the consequence is worth stating: measured here, a generator with schema = "billing" , sequenceName = "qr_numbers" and allocationSize = 50 , against a counter document saying increment: 1 , booted with no error and produced the identifiers 1, -47, -46. Users who both declare a schema on the generator and create the counter document by hand must get increment right themselves.
Other behaviour to document
Identifier allocation does not take part in the caller's transaction, which matches native SQL sequences. An allocated value is not returned when a transaction rolls back, so gaps between persisted identifiers are expected. A pooled optimizer also leaves a gap when a SessionFactory closes with part of its block unused, which with the default allocation size of 50 can be up to 49 identifiers per process.
Supported optimizers are none , pooled , pooled-lo , hilo and legacy-hilo . The last two are selected with the hibernate.id.optimizer.pooled.preferred setting.
Rejected at boot, each with a message giving the reason: GenerationType.IDENTITY (MongoDB has no auto-increment field and no way to return a generated key from an insert; use SEQUENCE , or the extension's @ObjectIdGenerator for a database-chosen identifier), GenerationType.TABLE ( HIBERNATE-252 ), GenerationType.UUID ( HIBERNATE-121 ), BigInteger and BigDecimal identifiers ( HIBERNATE-253 ), a non-blank @SequenceGenerator(options) , and a @GeneratedValue(generator) name that resolves to a non-sequence generator such as identity or increment , and a sequence qualified by a catalog.
The catalog one needs explaining in the manual, because the spelling is not guessable. Hibernate ORM reads a three-part sequenceName such as a.b.c as catalog a , schema b , sequence c , and this extension supports no catalog. Before it was rejected, the catalog was dropped when the counter key was formed, so that sequence shared one counter document with a plain schema = "b" , sequenceName = "c" and two entities drew identifiers from the same counter.
HQL insert ... select into an entity with a generated identifier remains unsupported, because MQL cannot embed an allocation inside another statement.