When a mapped class declares nothing about a column, what defaults apply, and why is that risky over time?
answer
- silence in the mapping, values in the schema
- opt-in versus opt-out member mapping
- nullability, length, precision get filled in
- a default reads exactly like a decision
- declare the load-bearing ones, validate the rest
basics
~20 sUndeclared elements still get values: which members are mapped, nullability, text length, numeric precision, the derived identifier. The risk is not that defaults are wrong but that a later reader cannot tell an unconsidered default from a deliberate decision.
solid answer
~50 sSilence in a mapping is never silence in the schema. A layer decides **which members are mapped** — usually every readable and writable member unless one is marked as not persisted — and then fills in **nullability**, **text length**, **numeric precision and scale**, and the derived identifier. Where the schema is generated from the model, those defaults become the shipped schema; where the schema is authored separately, they become the assumptions the layer validates against and can quietly disagree with. The failure mode is a reading failure: a column that permits absence because nobody thought about it looks identical to one that permits absence deliberately, and the next person to touch it has no way to tell. The practical response is to declare intent explicitly on load-bearing columns even when the declaration matches the default, and to run a startup check that compares the resolved mapping against the real schema.
go deeper
Know that leaving something undeclared does not leave it unset: the layer supplies nullability, sizes and the identifier, and those values reach the database.
Explain the specific defaults and the opt-in versus opt-out distinction, and describe how a wrong default surfaces differently in a generated schema versus a hand-authored one.
Show the operational habit: startup validation of the resolved mapping, review of generated definitions, and explicit declarations on the columns whose wrongness would cost a backfill later.
Frame it as schema governance — who reviews what the model implies about the database, and how the team keeps unexamined defaults from accumulating into structure nobody can justify.
Every mapping has two parts: what was written down, and what was filled in. The second part is larger than most teams realise, and it is where long-lived schemas accumulate decisions nobody made. ## What gets decided when nothing is declared - **Whether a member is mapped at all.** Layers differ on the default: some map every readable and writable member unless it is explicitly marked as not persisted (opt-out), others map only members that carry a declaration (opt-in). Under opt-out, adding a member to a class adds a column to the schema. Under opt-in, adding a member persists nothing and the omission is silent until someone notices data going missing. - **Nullability.** Some layers infer it from whether the member's type admits absence; others default everything to permitting null because that is the safe choice for a column being added to an existing table. - **Text length.** A textual column needs a size, and something picks one when nobody does. The number chosen is arbitrary from the domain's point of view and generous or stingy by accident. - **Numeric precision and scale.** A decimal column needs both. A default scale that is too small silently rounds monetary values; a default precision that is too small rejects large ones. - **The identifier itself.** The derived table or column name is a default like any other. - **Fetch and ordering defaults** for associations and collections, which belong to their own mapping concerns but arrive through the same silence. ## Where the default lands | How the schema is produced | Where the default ends up | Failure mode | |---|---|---| | Generated from the model | Directly in the shipped schema | A wrong default becomes a real column that later needs a migration | | Authored by hand, model validated against it | In the layer's expectations | Mismatch is caught at startup if validation is on, and at query time if it is not | | Authored by hand, no validation | Nowhere visible | The layer assumes one thing, the database holds another, and reads or writes fail on the unlucky row | ## The reading problem The deeper issue is not that a default is wrong — most defaults are reasonable. It is that a default and a decision are indistinguishable in the source. Consider a column that permits absence. It might be that way because absence is a real domain state, or because nobody said otherwise. A year later, someone deciding whether to make it required has to reconstruct which it was, and the code offers no evidence either way. The same ambiguity applies to a text length, a scale on a money amount, and whether a member is persisted at all. This is why defaults become decisions: not through a single bad choice, but through the accumulation of choices that were never examined and can no longer be distinguished from choices that were. ## Practices that keep it honest 1. **Declare intent on load-bearing elements even when it matches the default.** Stating that a column is required, or that a money amount has a specific scale, costs one line and converts an assumption into a documented decision. 2. **Turn on startup validation of the resolved mapping against the real schema.** It converts a silent divergence into a boot failure, which is the cheapest place to find one. 3. **Review generated schema output before it ships**, if the schema is generated. Reading the definition the layer produced is the only way to see the defaults it chose. 4. **Make the opt-in versus opt-out rule an explicit team convention**, so nobody has to guess whether adding a member adds a column. 5. **Keep a check on the members you deliberately do not persist**, because under an opt-out default a new computed member becomes a column, and under opt-in a new stored member becomes nothing. ## Where this bites in production The expensive cases share a pattern: the default was harmless when the table was small and became structural later. A generously sized text column costs nothing on ten thousand rows and matters on a hundred million. A decimal scale chosen by default rounds cents in a way that only appears in a reconciliation report. A column left nullable because nobody said otherwise accumulates rows with absent values, and by the time someone wants to make it required, backfilling is a project rather than a migration. None of these is a bug in the layer; each is an unexamined default that hardened into a fact. ## What a strong answer sounds like Name several things that get defaulted, distinguish opt-in from opt-out mapping, and then move to the real point: the reader cannot separate a default from a decision, so declare the ones that carry weight and validate the rest at startup. Mentioning that a wrong default in a generated schema turns into a migration, while a wrong default against a hand-authored schema turns into a startup or query failure, shows you have operated both arrangements.
- What is the practical difference between opt-in and opt-out member mapping?Under opt-out, every readable and writable member becomes a column unless it is marked as not persisted, so adding a computed member changes the schema. Under opt-in, only declared members are stored, so adding a member that should be stored silently persists nothing. Each has an opposite failure mode, and the team needs to know which one it is running.
- How does startup validation of the mapping against the schema help?It compares what the resolved mapping expects — tables, columns, types, nullability — against what the database actually has, and refuses to start on a mismatch. That turns a divergence that would otherwise surface as a failed query on an unlucky code path into a deterministic failure in the first environment the change reaches.
- Why declare something that already matches the default?Because the declaration records that a human considered it. A required column stated explicitly reads as a decision; the same column left implicit reads as an oversight. For elements where getting it wrong is expensive — nullability, monetary scale, whether a member is persisted — one line of declaration saves a later archaeology exercise.
saying these in an interview costs you the question
- Thinks nothing declared means nothing decided about the column
- Assumes every layer maps members by the same opt-in or opt-out rule
- Believes a default text length or numeric scale is domain-appropriate
- Never checks the schema the model would generate before shipping it
- Treats a nullable column as free to tighten later regardless of the data