Logical Deletion Semantics & Entity Mapping
Master soft delete mechanics, database existence vs application visibility boundaries, PATCH vs DELETE semantics, entity mapping, and state machines.
Logical Deletion Semantics & Entity Mapping
Soft Delete is a deletion strategy where an application does not physically destroy a database row. Instead, it mutates a status flag—such as is_deleted—to mark the record as logically inactive.
Hard Delete: DELETE FROM students WHERE id = 1 ──► Row physically destroyed
Soft Delete: UPDATE students SET is_deleted = true ──► Row physically retained, logically hidden1. High-Level Concept & The Archive Cabinet Analogy
Think of a filing cabinet at a university registrar's office:
THE ARCHIVE CABINET ANALOGY:
├── Active Student Record ──► File remains in the active drawer (is_deleted = false)
├── Archived Student Record ──► File is stamped "ARCHIVED" and moved to rear storage (is_deleted = true)
├── Hard Delete Operation ──► Shredding the paper file permanently
└── Soft Delete Operation ──► Stamping the file "ARCHIVED" without destroying it| Database / API Concept | Archive Cabinet Equivalent | Operational Role |
|---|---|---|
| Database Row | Student Paper File | Physical container of record data |
is_deleted = false | Active File | Visible to normal everyday operations |
is_deleted = true | Archived File | Retained for audit/history, hidden from normal reads |
PATCH /soft-delete | Stamp "ARCHIVED" | Partial state update operation |
DELETE /students/{id} | Paper Shredder | Permanent physical row destruction |
Core Architectural Rule: Physical database existence and application-level visibility are distinct concepts. Soft deletion changes a row's state; application queries must enforce visibility filtering rules.
2. Hard Delete vs Soft Delete Comparison
| Property Metric | Hard Delete (DELETE) | Soft Delete (PATCH /soft-delete) |
|---|---|---|
| Database State | Row physically removed | Row physically retained |
| HTTP Verb Semantics | DELETE /api/students/{id} | PATCH /api/students/{id}/soft-delete |
| Data Audit Trail | Lost permanently | Fully preserved |
| Application Recovery | Difficult (requires DB backups) | Simple (toggle is_deleted = false) |
| Query Requirement | Standard SQL queries | Queries MUST explicitly filter WHERE is_deleted = false |
3. Entity Mapping: Boolean vs Primitive boolean
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Column(name = "is_deleted", nullable = false)
private Boolean isDeleted = false; // Initialized to active state
public Student() {}
public Long getId() { return id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Boolean getIsDeleted() { return isDeleted; }
public void setIsDeleted(Boolean isDeleted) { this.isDeleted = isDeleted; }
}[!WARNING] Nullability Trap: Wrapper
Booleanallows three states (true,false,null). Ifnullhas no business meaning, enforce non-null integrity at the database column level (nullable = false) or use primitivebooleanto preventnullvisibility bugs.
4. Entity State Machine Transitions
❓ Knowledge Check
What is the fundamental difference between hard delete and soft delete at the database level?
Why is PATCH preferred over DELETE for soft-deletion HTTP endpoints?
DTOs, State Machines, Anti-Patterns & Debugging
Master DTO decoupling, CRUD state machine transitions, race condition avoidance, production anti-patterns, and outside-in debugging checklists.
Derived Query Methods & The findById Trap
Master Spring Data derived queries for soft delete, why default findAll() and findById() methods leak archived records, and clean repository interfaces.