Application Integration & Schema Evolution
ORM Impedance Mismatch
An ORM coordinates objects, identity, relationships, and changes over relational data, but object graphs and relations have different semantics. Use the abstraction deliberately, keep database constraints authoritative, and inspect the SQL and transaction behavior it emits.
- Object identity and relational keys differ.
- Associations are queries and constraints.
- Inheritance has no single relational mapping.
- Fetching is part of the API contract.
- Change tracking emits concurrency behavior.
- Abstractions leak at semantic boundaries.
| Concern | Object view | Relational/database reality | Control |
|---|---|---|---|
| Identity | reference / equals | primary/candidate key | stable key policy + identity map |
| Association | field/collection | FK or join relation | constraints + explicit ownership |
| Inheritance | subtype polymorphism | one/many tables | choose per query/constraint tradeoff |
| Fetching | navigation | round trips and row sets | projection/fetch plan + budgets |
| Change tracking | mutated fields | ordered DML under concurrency | version predicate + flush tests |
| Query leak | repository method | SQL types/plans/isolation | inspect SQL and real-engine behavior |
ALTER TABLE orders ADD COLUMN row_version BIGINT NOT NULL DEFAULT 0;
UPDATE orders
SET status = :new_status, row_version = row_version + 1
WHERE order_id = :order_id
AND row_version = :expected_version;
-- Exactly one affected row means the expected version won.
-- Zero means missing row or concurrent change; classify by the application contract.Order
identity: order_id
invariant: allowed status transition
children: OrderItem identified by (order_id, line_no)
concurrency token: row_version
Customer and Product are references by key, not automatically cascaded children.
Deletion, orphan removal, and loading are explicit use-case decisions.