I need to implement a rollback system and the memento pattern gets mentioned regularly as a solution to this requirement, but in all cases a single object is used and it works in memory, persistence is never discussed.

But what if I need to store the memento/state in a database? What if multiple objects are involved?

For instance, a user makes some changes affecting multiple tables. Here many rows and tables are involved, but we could say everything can be followed back to a single user instance. How can I adapt the memento pattern to

  • save the state of multiple (related) objects instead of a single one?

  • save the memento in the database, associate it with the user and create a state history system?

  • Hmm, I think you're confusing some concepts. Memento pattern is something you would use in-program to organize states. Persisting data to a database is not using memento pattern. It's simply saving the data. You would use a transaction to guarantee atomicity of the operation. Maybe I don't quite understand what you need to do. Can you give an example?
    – Neil
    Oct 9, 2018 at 11:00
  • @Neil Well but I need to save the state (which is held by the memento object) to the database. My example is a tournament instance having scheduled games (at a certain date, time, place... more information inter related). I need to be able to save the schedule at any given point so that if it changes in the future we can rollback to previous versions. I already implemented serialization/deserialization of a schedule (data saved in the database as a json string), but I am having trouble with the design of the actual rollback/undo system.
    – dabadaba
    Oct 9, 2018 at 11:09
  • Hmm, I see what you mean. Let me think on it and I'll write an answer shortly.
    – Neil
    Oct 9, 2018 at 11:10

2 Answers 2


You actually have two problems:

  1. You need to implement a rollback mechanism
  2. You need to store each edit in the database

These require two different solutions.

If you have a traditional web application with POSTs back to the server to modify data, then the Memento pattern is not really appropriate here. You just need a way to store revisions to records in multiple tables in a database.

Since you are entertaining the Memento Pattern, I'm going to assume there is a richer client than just a dumb web page and a form.

The Memento Pattern will take care of modifications to application state in memory. Persistence, and the ability to roll changes back from persistence should be separate logic. So your first order of business is to implement the Memento Pattern without persistence. After that you need a data model that allows revisions to records in a database.

Let's say you have a blog application, and you need to save revisions to a blog post. You'll need two tables:

  1. BlogPosts
  2. BlogPostRevisions

The BlogPosts table would really just be a glorified primary key and a foreign key to the blog post revisions table:

| BlogPosts              |           +-------------------+
+------------------------+           | BlogPostRevisions |
| (PK) Id                |           +-------------------+
| (FK) CurrentRevisionId | -|------< | (PK) RevisionId   |
+------------------------+           |      Title        |
                                     |      Body         |
                                     |      PublishDate  |
                                     |      CreateDate   |

Creating a blog post creates 2 records across two different tables:

  1. A record in the BlogPosts table
  2. A record in the BlogPostRevisions table

An update to the blog post inserts a new record into the BlogPostRevisions table with all the current (and newly changed) values for the blog post. The CurrentRevisionId column in the BlogPosts table gets updated to the new revision Id.

Rolling back to a previous revision is as simple is changing the CurrentRevisionId, or simply copying an existing revision and inserting it as the newer revision.

In short, keep the in-memory rollback mechanism (undo) different from the persisted rollback mechanism. The Memento Pattern doesn't address persistence, and persistence doesn't necessarily make for the most intuitive and responsive "undo" mechanism. You have two problems that deserve two different solutions.


So as I understand it, you're currently using a Memento pattern to hold scheduling information, and your question pertains to how you can integrate this with a database.

Well the memento object must be able to save and restore the current state of a schedule. The actual saving of the state happens when the memento is created, so my idea is that you should grab all the data as you do already, but then you immediately persist that data to the database. The data can expand multiple tables, but have a parent table to deal with a memento instance to record one-to-one relationship. When you persist this instance, get its unique id that identifies that record and lets you retrieve all the data. This id then gets sent back to the memento. This means the memento now holds all the data and the id associated with it in the database, right?

Use the memento as you would normally. It has all the data already present and you should be able to continue using it normally throughout your program.

Now what about the scenario in which your program starts up and you need to restore a particular memento? You have a table with all your memento states saved! Grab a list of all their ids, and create a memento containing only the ids for each record.

When the data is requested for restoration, at this point, use the id to load all the information from the database. In this way, your program uses the mementos transparently. The memento state is persisted to the database, and everyone is happy. :)

You may or may not decide to hold onto the data you persisted with the memento. With this functionality, you can also choose to abandon the data in favor of holding just the id itself (so if the data is needed, you can once again retrieve it from the database). If you have the memory for it, and you think that data will be useful again, you may choose to simply hold onto the data to avoid necessarily having to load it again from the database.

I don't know what language you're using, but some languages such as Java support soft references which would be ideal here, which frees up the space in memory only if memory is required. Good luck!

  • Can you check out if I got the right idea?: pastebin.com/CvUmajSw All diagrams I see are actually missing the caretaker part. As you can see, I am creating a new memento with the persisted data so we can restore from it, which honestly doesn't make much sense... But I don't want to keep the serialized data in memory. I don't see any other way around it. Actually, I am forced to instantiate the memento object myself, otherwise a new row would be inserted in the database. I don't think this is how it is supposed to work.
    – dabadaba
    Oct 9, 2018 at 12:46
  • @dabadaba Almost. I was thinking the Memento class itself would perform the lookup and insertion. Except for the Memento class, the rest of your program wouldn't even need to know that the data were being persisted to a database. Doing it like this, you minimize impact on the program.
    – Neil
    Oct 9, 2018 at 14:17
  • yeah well, I could see the persistence part both in the memento and the originator, but given my case where I need to instantiate a memento that already existed then I need to do it in the originator
    – dabadaba
    Oct 9, 2018 at 14:36
  • By the way don't you think my caretaker kind of defeats the purpose of the entire pattern? When restoring, a database lookup is performed to get the appropriate snapshot, and then we instantiate a memento so we can pass it to originator.restore. Technically the originator doesn't need a memento object, it just needs the deserialized data... It just feels weird instantiating a memento that was already instantiated when the snapshot was created in the past.
    – dabadaba
    Oct 9, 2018 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.