javadatabase-designsoftware-design

Database level design for undo operation


I have an entity "MyEntity" which has some fields - "StartDate", "EndDate", "Color".

It can have multiple records, and each record is sometimes updated. I need to keep track of what updates were performed on each record and perform an "undo" operation and restore that record to previous state.

I have heard of memento design pattern, but that's mostly in-memory. I need a solution where this information is stored at database level. If i go to a record of MyEntity, and click "Undo" button, it should revert the last update.

Are there any recommendation on best data model on how to store that info in database?

Example,

MyEntityRecord1 (created) -> Jan1-2025, Dec31-2025, Blue

MyEntityRecord1 (updated) -> Jan1-2025, May30-2025, Blue

MyEntityRecord1 (updated) -> Jan1-2025, May30-2025, Red

MyEntityRecord1 (updated) -> Jan20-2025, May30-2025, Purple

MyEntityRecord1 (first undo) -> Jan1-2025, May30-2025, Red

MyEntityRecord1 (second undo) -> Jan1-2025, May30-2025, Blue

Thats the kind of functionality i am looking at. Side note: We cannot undo and undo operation.

Our database stores only the latest state of MyEntityRecord1. For undo to work, i need some sort of diff on what changes were made on last operation.

At the top of my head, I probably need to create another entity in database (MyEntityUpdates), that stores all intermediate states (and reference to the MyEntity record), but not too sure if thats the best design.

We use a relational database, if that information is any use and run SQL queries


Solution

  • You'll probably want some kind of audit/history table. This is a common pattern in some apps, often referred to as "event sourcing" or "audit trails", depending on depth and use case.

    A little schema

    MyEntity

    Column Name Type Description
    id INTEGER primary key
    start_date DATE start date of the entity
    end_date DATE end date of the entity
    color TEXT color of the entity

    MyEntityHistory

    Column Name Type Description
    id INTEGER primary key
    entity_id INTEGER foregin key to MyEntity(id)
    start_date DATE snapshot start date
    end_date DATE snapshot end date
    color TEXT color of snapshot
    version INTEGER auto increment per entity
    updated_at TIMESTAMP time when the update occurred
    change_type TEXT (optional) what kind of change 'update', 'undo', 'create', etc.
    performed_by TEXT (optional) who made the change (useful depending on use case)

    update to MyEntity triggers insert into MyEntityHistory before the change is applied, storing the pre-change state. Or you can do it after applying and store the new state; both are valid depending on what you want.