In a data-access layer that maps a link from both classes, what does it mean that one end owns the write?
answer
- one stored slot, two object views
- only one end emits the statement
- inverse end is read-only at flush
- the column's table suggests the owner
- ownership is not cascade
basics
~20 sThe owning end is the side whose state the mapper turns into the foreign-key or junction-row statement. The other end is mapped for reading and navigation: changing it alone normally produces no SQL at all.
solid answer
~50 sThe stored link sits in one place — a foreign-key column on one row, or a row in a junction table — while the object model can expose it from both sides. The mapping names which side the layer reads when it builds statements. That **owning end** is dirty-checked and turned into an `UPDATE` of the link column or an `INSERT`/`DELETE` of a junction row; the **inverse end** is populated on load and navigated in code, but derives no statement in layers that draw the distinction. For a one-to-many link the column lives on the child row, so the child's reference is the natural owner. For a junction link either side can be declared the owner, because the junction row belongs to neither table. Ownership of the write is a separate declaration from cascade, which decides lifecycle.
go deeper
Remember the shape: the link is stored once, the objects can show it twice, and only one of those views is what gets written. Be able to say which side that normally is for a parent-and-children link.
Explain the mechanics — the dirty check runs over the owning field, the inverse end is populated on load, and statement ordering is the layer's decision. Say why a foreign-key link constrains the choice and a junction link does not.
Show that you use the declaration deliberately: pick the owner that matches the side your code edits, keep cascade decisions separate from it, and know which behaviours your layer will and will not fill in for you.
Treat it as an API-shape decision. A model where either end can be set independently will produce half-set links across a whole codebase, so the standard you set is that links are changed through one method, not that everyone remembers which end wins.
A link between two rows lives in exactly one place in the stored data: a **foreign-key column** on one of the two tables, or a **row in a junction table**. The object model can show that same link from both directions — a parent holding a collection of children, and each child holding a reference back to the parent. Two in-memory views, one storage slot. Something has to decide which view the layer reads when it builds the statement, because reading both would force it to resolve their disagreements on every flush. That decision is the **owning end**, and it is written into the mapping rather than inferred from the code that runs. ## One link, two views - **Owning end** — the side the layer inspects when it works out what to write. Its state becomes an `UPDATE child SET parent_id = ?`, an `INSERT` into the junction table, or a `DELETE` of a junction row. - **Inverse end** — mapped so the graph can be navigated and so the layer can populate it on load. In layers that draw this distinction, the inverse end derives no statement: code can add to that collection freely and the stored data does not move. - The distinction exists only because the link is mapped **twice**. A link mapped from a single side is trivially owned by that side, and the word rarely comes up. ## What the owning end does at flush 1. The layer compares the owning field's current value with the value it recorded when the object was loaded — the same dirty check it runs over every other mapped field. 2. Any difference becomes a statement against the column or the junction table. The inverse collection is not consulted. 3. Statement order is the layer's choice, not the calling code's: it will normally insert a parent before the child that points at it, and delete junction rows before the rows they reference. 4. Whatever the inverse side holds in memory is left exactly as the code left it. Nothing reconciles the two views for you unless the mapping explicitly asks for it. ## Which end can own | Link shape | Where the stored link sits | Which end normally owns it | |---|---|---| | One parent, many children | foreign-key column on the child row | the child's reference to the parent, because the column is on that row | | One row to one row | foreign-key column on one of the two rows | the side that carries the column | | Many to many | a junction row belonging to neither table | either side, decided by declaration | The pattern behind the table is simple: **the owner is whoever the storage lets you write in one statement.** For a foreign-key link, only the child's row can be updated to change the link, so declaring the parent's collection as the owner either is impossible or costs the layer extra statements. For a junction link, neither row changes, so the choice is genuinely free and is usually made by whichever side the application code edits. ## Ownership is not lifecycle Owning the write says which field the layer reads. It says nothing about which object matters more, which one is loaded first, or what happens to the other when one is deleted. Whether saving a parent also saves a new child, and whether deleting a parent deletes its children, is a **separate declaration** (cascade). Interviews routinely conflate the two, and the giveaway is a candidate who answers "the parent owns it, because the children belong to it" for a link whose foreign key sits on the child. ## Layers without a tracked set A query builder or a thin statement layer keeps no tracked copy of what it loaded and runs no dirty check, so the concept does not arise: the code writes the foreign-key column or the junction row itself, and there is no second view to fall out of step. Full mappers also differ from one another — some will keep both ends aligned when the pair is declared as one bidirectional link, others deliberately will not, on the grounds that guessing is worse than a rule. Treating the friendlier behaviour as universal is how the classic one-end-set defect ships. ## What an interviewer is listening for - Naming the storage location first — one column, or one junction row — and deriving the rest from it. - Stating that the inverse end is a read and navigation convenience at write time. - Separating the owning declaration from cascade. - Not claiming the layer compares both ends and picks a winner. - Knowing that the answer changes shape for a junction link, where either side can be declared the owner.
- For a link stored in a junction table, why can either side be declared the owner?Neither row changes when the link changes — the layer inserts or deletes a junction row instead. Since the statement targets a third table, nothing about the storage forces the choice, so the mapping picks whichever side the application code actually edits.
- Is the owning end also the side that decides whether saving one object saves the other?No. Ownership says which field the layer reads to build the link statement. Whether a save or delete propagates along the link is a separate cascade declaration, and it can be declared on the end that does not own the write.
- Does the concept apply to a layer that does not track loaded objects?Not really. Without a tracked snapshot there is no dirty check and no second mapped view to fall out of step: the code writes the foreign-key column or the junction row itself, so the question of which end the layer reads never arises.
Two calendars showing the same meeting. Only one of them is the copy the scheduling system reads when it sends the invitations; editing the other changes what you see and nothing else.
saying these in an interview costs you the question
- Thinks both ends of a mapped link produce statements independently
- Says the parent's collection is what emits the foreign-key update
- Claims the owning side is a free choice for every link shape
- Assumes the layer compares both ends and reconciles them at flush
- Confuses owning the write with owning the lifecycle of the other object