Required columns and backfills
A column becomes required only when no row holds NULL. The values for existing rows come from a backfill you register.
Nullable first, NOT NULL after counting
A new required column in an existing table is added nullable. It becomes required with SET NOT NULL after the executor has counted under the lock that no row holds NULL. Any NULL left makes the migration fail and roll back.
So a new required column works in an empty table, and a column becomes required once its rows are filled. It becomes optional again with DROP NOT NULL; primary key and identity columns stay required.
Values the application declares
The framework never invents a value. A backfill names its target column by ID, runs when the column becomes required and fills only the NULLs.
What a backfill may use
Constants are always JDBC parameters. A constant must fit the column without conversion or rounding, a source column must have the target's type, or be text for text.
- BackfillValue.literal(value)
- A constant: text, numbers, boolean, UUID, date and time types.
- BackfillValue.column(id)
- Another column of the same row, by stable ID.
- BackfillValue.coalesce(values*)
- The first value that is not NULL.
- BackfillValue.concat(values*)
- Text joined together; NULL if any part is NULL.
Registered once, run once
A backfill is recorded with its definition's checksum in __hibernate_ddl.backfill_history. The same ID with another definition blocks the start.
They run in its transaction while its tables are locked exclusively. Large tables and deployments without downtime need a separate, stepwise data migration.